//
// Created on 2025/1/13.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#include "core/SkBitmap.h"
#include "core/SkCanvas.h"
#include "core/SkColorFilter.h"
#include "core/SkData.h"
#include "core/SkFontTypes.h"
#include "core/SkImage.h"
#include "core/SkPaint.h"
#include "core/SkPath.h"
#include "core/SkPathTypes.h"
#include "core/SkPictureRecorder.h"
#include "core/SkPoint3.h"
#include "core/SkRRect.h"
#include "core/SkStream.h"
#include "core/SkVertices.h"
#include "effects/SkColorMatrix.h"
#include "effects/SkColorMatrixFilter.h"
#include "effects/SkDashPathEffect.h"
#include "effects/SkGradientShader.h"
#include "effects/SkHighContrastFilter.h"
#include "effects/SkLumaColorFilter.h"
#include "effects/SkOverdrawColorFilter.h"
#include "include/effects/Sk1DPathEffect.h"
#include "include/effects/SkCornerPathEffect.h"
#include "include/pathops/SkPathOps.h"
#include "modules/skparagraph/include/FontCollection.h"
#include "modules/skparagraph/include/Paragraph.h"
#include "modules/skparagraph/include/ParagraphBuilder.h"
#include "modules/skparagraph/include/ParagraphStyle.h"
#include "modules/skparagraph/include/TextStyle.h"
#include "modules/skparagraph/include/TypefaceFontProvider.h"
#include "modules/svg/include/SkSVGDOM.h"
#include "src/base/SkUTF.h"
#include "src/core/SkReadBuffer.h"
#include "src/xml/SkDOM.h"
#include "src/xml/SkXMLWriter.h"
#include "testing/Testing.h"
#include "utils/SkShadowUtils.h"
#include "utils/log.h"
#include <atomic>
#include <fstream>
#include <iostream>
#include <memory>


DEF_TEST_CANVAS(ClearColor1, TEST_LEVEL::NORMAL) {
    // will change and redraw
    static int colorGreen = 0;
    test_canvas.clear(SkColorSetARGB(128, 255, colorGreen, 0)); 
    colorGreen = (colorGreen + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor2, TEST_LEVEL::NORMAL) {
    // will not change and not redraw
    static int colorRed = 0;
    test_canvas.clear(SkColorSetARGB(255, colorRed, 128, 0));
    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 3000, 400));
    test_canvas.clear(SkColorSetARGB(255, 0, 128, 255));
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor3, TEST_LEVEL::NORMAL) {
    // will change and redraw
    static int colorRed = 0;
    test_canvas.clear(SkColorSetARGB(255, colorRed, 128, 0));
    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 300, 400));
    test_canvas.clear(SkColorSetARGB(255, 0, 128, 255));
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor4, TEST_LEVEL::NORMAL) {
    // will change and redraw
    static int colorRed = 0;
    test_canvas.clear(SkColorSetARGB(255, 0, 150, 0));
    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 3000, 400));
    test_canvas.clear(SkColorSetARGB(255, colorRed, 150, 255));
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor5, TEST_LEVEL::NORMAL) { 
    // will change and redraw
    static int colorRed = 0;
    test_canvas.clear(SkColorSetARGB(255, 0, 150, 0));
    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 300, 400));
    test_canvas.clear(SkColorSetARGB(255, colorRed, 150, 255));
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor6, TEST_LEVEL::NORMAL) { 
    // will change and redraw
    test_canvas.clear(SkColorSetARGB(255, 0, 180, 0));
    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 200, 400));
    static int colorRed = 0;
    SkPaint paint;
    paint.setColor(SkColorSetARGB(255, colorRed, 0, 0));
    auto rect = SkRect::MakeXYWH(0, 0, 3000, 300);
    test_canvas.drawRect(rect, paint); 
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(ClearColor7, TEST_LEVEL::NORMAL) {
    // will not change and not redraw
    static int colorRed = 0;
    test_canvas.clear(SkColorSetARGB(255, colorRed, 180, 0));
//    test_canvas.clipRect(SkRect::MakeXYWH(0, 0, 200, 400));
    SkPaint paint;
    paint.setColor(SkColorSetARGB(255, 0, 0, 0));
    auto rect = SkRect::MakeXYWH(0, 0, 3000, 300);
    test_canvas.drawRect(rect, paint); 
    colorRed = (colorRed + 63) % 256;
}

DEF_TEST_CANVAS(drawRect1, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    SkPaint paint;
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setColor(SK_ColorBLUE);
    paint.setStrokeWidth(20);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    SkPaint paint_copy = paint;
    paint_copy.setStyle(SkPaint::kStroke_Style);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint_copy);
    start_X += width * 1.3;

    paint.setStrokeMiter(0);
    paint.setStrokeWidth(20);
    paint.setStyle(SkPaint::kStroke_Style);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    SkPaint paint_move = std::move(paint);
    paint_move.setAlpha(128);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint_move);
    start_X += width * 1.3;

    paint_move.setStrokeJoin(SkPaint::Join::kRound_Join);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint_move);
    start_X += width * 1.3;

    paint_move.setStrokeJoin(SkPaint::Join::kBevel_Join);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint_move);
    start_X += width * 1.3;

    paint.setColor(SK_ColorBLUE);
    paint.setStrokeWidth(20);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;
}

DEF_TEST_CANVAS(drawLinePoint1, TEST_LEVEL::NORMAL) {
    float start_X = 50.f;
    float width = 50.f;

    // draw line
    SkPaint paint;
    paint.setStrokeWidth(20);
    paint.setStroke(true);
    test_canvas.drawLine(start_X, 50, start_X, 250, paint);
    start_X += width * 1.3;

    paint.setColor(SK_ColorRED);
    test_canvas.drawLine(start_X, 50, start_X, 250, paint);
    start_X += width * 1.3;

    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    test_canvas.drawLine(start_X, 50, start_X, 250, paint);
    start_X += width * 1.3;

    paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
    test_canvas.drawLine(start_X, 50, start_X, 250, paint);
    start_X += width * 1.3;

    // draw point
    paint.setStrokeWidth(50);
    test_canvas.drawPoint(start_X, 50, paint);
    start_X += width * 1.3;

    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    test_canvas.drawPoint(start_X, 50, paint);
    start_X += width * 1.3;

    // draw points
    SkPoint points1[] = {{start_X, 50}, {start_X, 100}, {start_X, 150}, {start_X + 30, 200}};
    paint.setStrokeWidth(20);
    test_canvas.drawPoints(SkCanvas::PointMode::kPoints_PointMode, 4, points1, paint);
    start_X += width * 1.5;

    SkPoint points2[] = {{start_X, 50}, {start_X, 100}, {start_X, 150}, {start_X + 10, 200}};
    test_canvas.drawPoints(SkCanvas::PointMode::kLines_PointMode, 4, points2, paint);
    start_X += width * 1.5;

    SkPoint points3[] = {{start_X, 50},       {start_X, 100},      {start_X, 150},    {start_X + 10, 200},
                         {start_X + 20, 220}, {start_X + 30, 250}, {start_X + 5, 250}};
    test_canvas.drawPoints(SkCanvas::PointMode::kLines_PointMode, 7, points3, paint);
    start_X += width * 1.5;

    SkPoint points4[] = {{start_X, 50}, {start_X, 100}, {start_X, 150}, {start_X + 10, 200}};
    test_canvas.drawPoints(SkCanvas::PointMode::kPolygon_PointMode, 4, points4, paint);
    start_X += width * 1.5;
}

DEF_TEST_CANVAS(drawLineAntiAlias, TEST_LEVEL::NORMAL) {
    float start_X = 50.f;
    float width = 50.f;

    // draw line
    SkPaint paint;
    paint.setStrokeWidth(50);
    paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
    paint.setStroke(true);
    paint.setAntiAlias(false);
    paint.setColor(SK_ColorRED);
    test_canvas.drawLine(start_X, 50, start_X + 400, 250, paint);
    start_X += width * 3;
    
    paint.setStrokeCap(SkPaint::Cap::kButt_Cap);
    test_canvas.drawLine(start_X, 50, start_X + 400, 250, paint);
    start_X += width * 3;
    
    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    test_canvas.drawLine(start_X, 50, start_X + 400, 250, paint);
    start_X += width * 3;
    
    paint.setAntiAlias(true);
    test_canvas.drawLine(start_X, 50, start_X + 400, 250, paint);
    start_X += width * 3;
}

DEF_TEST_CANVAS(drawRectBlend, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    test_canvas.clear(SkColorSetARGB(255, 0, 255, 0));

    SkPaint paint;
    paint.setColor(SkColorSetARGB(200, 255, 0, 0));

    paint.setBlendMode(SkBlendMode::kSrcOver);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kSrcIn);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kSrcOut);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kSrcATop);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kDstOver);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kDstIn);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kDstOut);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    paint.setBlendMode(SkBlendMode::kDstATop);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;
}

DEF_TEST_CANVAS(drawRectBlurMaskFilter, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    SkPaint paint;

    paint.setColor(SK_ColorRED);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkMaskFilter> blurFilter1 = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10.0f);
    paint.setMaskFilter(blurFilter1);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkMaskFilter> blurFilter2 = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 30.0f);
    paint.setMaskFilter(blurFilter2);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkMaskFilter> blurFilter3 = SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 10.0f);
    paint.setMaskFilter(blurFilter3);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkMaskFilter> blurFilter4 = SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 10.0f);
    paint.setMaskFilter(blurFilter4);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkMaskFilter> blurFilter5 = SkMaskFilter::MakeBlur(kInner_SkBlurStyle, 10.0f);
    paint.setMaskFilter(blurFilter5);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;
}

DEF_TEST_CANVAS(drawRectColorFilter1, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    SkPaint paint;

    paint.setColor(SkColorSetARGB(255, 128, 0, 0));
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    // blend
    sk_sp<SkColorFilter> color_filter = SkColorFilters::Blend(SkColorSetARGB(100, 0, 255, 0), SkBlendMode::kSrcOver);
    paint.setColorFilter(color_filter);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    SkColorMatrix matrix;
    // enhance red
    matrix.setScale(10.0f, 1.0f, 1.0f, 1.0f);
    sk_sp<SkColorFilter> color_filter2 = SkColorFilters::Matrix(matrix);
    paint.setColorFilter(color_filter2);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    SkColorMatrix matrix1;
    matrix1.setScale(-1.0f, -1.0f, -1.0f, 1.0f);
    matrix1.postTranslate(1.0f, 1.0f, 1.0f, 0);
    paint.setColor(SkColorSetARGB(255, 128, 255, 0));
    sk_sp<SkColorFilter> color_filter5 = SkColorFilters::Matrix(matrix1);

    // compose sequence
    // 128,255,0 => 255,255,0 => 0,0,255
    sk_sp<SkColorFilter> color_filter6 = SkColorFilters::Compose(color_filter5, color_filter2);
    paint.setColorFilter(color_filter6);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    // 128,255,0 => 128,0,255 => 255,0,255
    sk_sp<SkColorFilter> color_filter7 = SkColorFilters::Compose(color_filter2, color_filter5);
    paint.setColorFilter(color_filter7);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    paint.setColor(SK_ColorRED);
    paint.setColorFilter(nullptr);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkColorFilter> color_filter8 =
        SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(128, 128, 128), SkColorSetRGB(64, 64, 64));
    paint.setColorFilter(color_filter8);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;
}

DEF_TEST_CANVAS(drawRectColorFilter2, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    // not support: SkColorFilters::Table SkColorFilters::TableARGB
    SkPaint paint;

    paint.setColor(SkColorSetRGB(96, 64, 32));
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkColorFilter> color_filter2 = SkColorFilters::LinearToSRGBGamma();
    paint.setColorFilter(color_filter2);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    sk_sp<SkColorFilter> color_filter3 = SkColorFilters::SRGBToLinearGamma();
    paint.setColorFilter(color_filter3);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;


    sk_sp<SkColorFilter> color_filter4 = SkLumaColorFilter::Make();
    paint.setColorFilter(color_filter4);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;
}

DEF_TEST_CANVAS(drawRectColorShader, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    SkPaint paint;

    SkColor color = SkColorSetARGB(255, 255, 0, 0);
    auto shader = SkShaders::Color(color);
    paint.setShader(shader);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    // not support: shader colorspace
    auto color1 = SkColor4f::FromColor(SkColorSetARGB(255, 0, 255, 0));
    auto colorSpace = SkColorSpace::MakeSRGB();
    shader = SkShaders::Color(color1, colorSpace);
    paint.setShader(shader);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    paint.setShader(SkShaders::Empty());
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    // 定义渐变的起点和终点
    SkPoint points[2] = {{start_X, 50}, {start_X + width + 200, 50}};

    
    SkColor colors[4] = {0x00FF0000, 0xFFFF0000, 0x0000FF00, 0xFF00FF00};
    SkScalar pos[4] = {0, 0.25, 0.75, 1};
    // 生成线性渐变 Shader
    sk_sp<SkShader> shader1 = SkGradientShader::MakeLinear(points, colors, pos, 4, SkTileMode::kClamp, 1);
    paint.setShader(shader1);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    test_canvas.drawRect({start_X, 50, start_X + width + 200, 200}, paint);
    start_X += width * 1.5 + 200;


    SkPoint center = SkPoint::Make(start_X + 30, 100);
    sk_sp<SkShader> shader2 = SkGradientShader::MakeRadial(center, 80, colors, nullptr, 2, SkTileMode::kClamp);
    paint.setShader(shader2);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;


    center = SkPoint::Make(start_X + 50, 125);
    SkColor colors4[] = {SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN};
    SkScalar positions[] = {0.0f, 0.5f, 1.0f}; // 颜色在渐变中的位置
                                               // 额外参数：startAngle 和 endAngle
    SkScalar startAngle = 0.0f;                // 从 0° 开始渐变
    SkScalar endAngle = 360.0f;                // 结束在 360°

    SkMatrix localMatrix;
    localMatrix.setRotate(45, center.fX, center.fY); // 围绕渐变中心旋转 45°
    sk_sp<SkShader> shader3 = SkGradientShader::MakeSweep(center.fX, center.fY, // 渐变中心点
                                                          colors4, positions, 3, // 颜色数组、颜色位置、颜色数量
                                                          SkTileMode::kClamp,   // 颜色填充模式
                                                          startAngle, endAngle, // 起始角度、终止角度
                                                          0, &localMatrix);
    paint.setShader(shader3);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;

    center = SkPoint::Make(start_X + 50, 125);
    SkScalar positions1[] = {0.0f, 0.5f, 1.0f}; // 颜色在渐变中的位置
                                                // 额外参数：startAngle 和 endAngle
    startAngle = 90.0f;                         // 从 90° 开始渐变
    endAngle = 270.0f;                          // 结束在 270°

    sk_sp<SkShader> shader4 = SkGradientShader::MakeSweep(center.fX, center.fY, // 渐变中心点
                                                          colors4, positions1, 3, // 颜色数组、颜色位置、颜色数量
                                                          SkTileMode::kClamp,   // 颜色填充模式
                                                          startAngle, endAngle, // 起始角度、终止角度
                                                          0, nullptr);
    paint.setShader(shader4);
    test_canvas.drawRect({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.5;


    SkScalar positions2[] = {0.0f, 0.5f, 1.0f};

    // 圆锥渐变的两个焦点（小圆中心和大圆中心）
    SkPoint start = SkPoint::Make(start_X + 50, 100);       // 小圆中心
    SkScalar startRadius = 20;                              // 小圆半径
    SkPoint end = SkPoint::Make(start_X + width + 50, 150); // 大圆中心
    SkScalar endRadius = 150;                               // 大圆半径

    // 创建渐变着色器
    sk_sp<SkShader> shader5 =
        SkGradientShader::MakeTwoPointConical(start, startRadius,     // 小圆
                                              end, endRadius,         // 大圆
                                              colors4, positions2, 3, // 颜色 & 位置
                                              SkTileMode::kClamp // Tile 模式（kClamp: 超出范围的部分保持边缘颜色）
        );

    paint.setShader(shader5);
    test_canvas.drawRect({start_X, 50, start_X + width + 50, 200}, paint);
    start_X += width * 1.5;
}

// Helper function to read font data from a file
sk_sp<SkData> ReadFontData(const char *fontPath) {
    std::ifstream file(fontPath, std::ios::binary | std::ios::ate);
    if (!file.is_open()) {
        SkDebugf("Failed to open font file: %s \n", fontPath);
        return nullptr;
    }

    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg);

    auto buffer = SkData::MakeUninitialized(size);
    if (!file.read(reinterpret_cast<char *>(buffer->writable_data()), size)) {
        SkDebugf("Failed to read font data from file.\n");
        return nullptr;
    }

    return buffer;
}

// auto g_myTypeface =
// SkTypeface::MakeFromFile("/data/storage/el1/bundle/entry/resources/resfile/YiShanBeiZhuanTi.ttf");
auto g_myTypeface =
    SkTypeface::MakeFromData(ReadFontData("/data/storage/el1/bundle/entry/resources/resfile/YiShanBeiZhuanTi.ttf"));

DEF_TEST_CANVAS(drawText, TEST_LEVEL::NORMAL) {
    sk_sp<skia::textlayout::FontCollection> fontCollection = sk_make_sp<skia::textlayout::FontCollection>();
    auto fontmgr = SkFontMgr::RefDefault();
    auto assetmgr = sk_make_sp<skia::textlayout::TypefaceFontProvider>();
    fontCollection->setDefaultFontManager(fontmgr);
    fontCollection->setAssetFontManager(assetmgr);
    //    auto g_myTypeface = SkTypeface::MakeFromFile(Testing::GetInstance().getFontPath().c_str());
    assetmgr->registerTypeface(g_myTypeface);
    // 创建段落样式
    skia::textlayout::ParagraphStyle paragraphStyle;

    // 创建段落构建器
    auto builder = skia::textlayout::ParagraphBuilder::make(paragraphStyle, fontCollection);

    // 设置文本样式 1
    skia::textlayout::TextStyle textStyle1;
    textStyle1.setFontSize(50);                                             // 字体大小
    textStyle1.setColor(SK_ColorBLACK);                                     // 文本颜色
    textStyle1.setDecoration(skia::textlayout::TextDecoration::kUnderline); // 添加下划线
    textStyle1.setDecorationColor(SK_ColorRED);                             // 设置下划线颜色
    textStyle1.setLetterSpacing(2.0f);                                      // 设置字符间距
    textStyle1.setWordSpacing(5.0f);                                        // 设置单词间距
    textStyle1.setHeight(1.5f);                                             // 行高
    textStyle1.setTypeface(g_myTypeface);
    builder->pushStyle(textStyle1);
    builder->addText("你好，世界(typeface)");

    // 设置文本样式 2
    skia::textlayout::TextStyle textStyle2;
    textStyle2.setFontSize(40);                                                                        // 字体大小
    textStyle2.setColor(SK_ColorBLUE);                                                                 // 文本颜色
    textStyle2.addShadow(skia::textlayout::TextShadow(SK_ColorBLACK, SkPoint::Make(5.0f, 5.0f), 3.0)); // 添加阴影
    SkString fontName;
    g_myTypeface->getFamilyName(&fontName);
    textStyle2.setFontFamilies({fontName});         // 设置字体族
    textStyle2.addFontFeature(SkString("liga"), 1); // 添加字体特性
    textStyle2.setBaselineShift(10.0f);             // 设置基线偏移
    builder->pushStyle(textStyle2);
    builder->addText("你好，世界(fontname)\n");

    // 设置文本样式 3
    skia::textlayout::TextStyle textStyle3;
    textStyle3.setFontSize(60);                                              // 字体大小
    textStyle3.setColor(SK_ColorGREEN);                                      // 文本颜色
    textStyle3.setHalfLeading(true);                                         // 启用半行间距
    textStyle3.setTextBaseline(skia::textlayout::TextBaseline::kAlphabetic); // 设置文本基线
    builder->pushStyle(textStyle3);
    builder->addText("This is a test.\n");

    // 设置文本样式 4（带背景颜色）
    skia::textlayout::TextStyle textStyle4;
    textStyle4.setFontSize(30);                                                    // 字体大小
    textStyle4.setColor(SK_ColorWHITE);                                            // 文本颜色
    textStyle4.setBackgroundPaint(SkPaint(SkColor4f::FromColor(SK_ColorDKGRAY)));  // 设置背景颜色
    textStyle4.setDecoration(skia::textlayout::TextDecoration::kLineThrough);      // 添加删除线
    textStyle4.setDecorationStyle(skia::textlayout::TextDecorationStyle::kDotted); // 设置删除线样式为点状
    builder->pushStyle(textStyle4);
    builder->addText("Background text.\n");

    // 构建段落
    std::unique_ptr<skia::textlayout::Paragraph> paragraph = builder->Build();

    // 设置段落宽度并布局
    paragraph->layout(1000);               // 设置宽度
    paragraph->paint(&test_canvas, 50, 0); // 绘制文本到 Canvas 上
}

DEF_TEST_CANVAS(drawText2, TEST_LEVEL::NORMAL) {
    sk_sp<skia::textlayout::FontCollection> fontCollection = sk_make_sp<skia::textlayout::FontCollection>();
    fontCollection->setDefaultFontManager(SkFontMgr::RefDefault());

    // **第一段落样式和内容**
    skia::textlayout::ParagraphStyle paragraphStyle;
    paragraphStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
    paragraphStyle.setMaxLines(2);               // 限制最多显示 2 行
    paragraphStyle.setEllipsis(SkString("...")); // 超出部分显示省略号
    paragraphStyle.setHeight(1.5f);              // 设置段落的行高
    skia::textlayout::TextIndent indent;
    indent.setFirstLine(20.f);
    indent.setRestLine(10.f);
    paragraphStyle.setTextIndent(indent);

    auto builder = skia::textlayout::ParagraphBuilder::make(paragraphStyle, fontCollection);

    // 文本样式
    skia::textlayout::TextStyle textStyle1;
    textStyle1.setFontSize(50);                                             // 字体大小
    textStyle1.setColor(SK_ColorBLACK);                                     // 文本颜色
    textStyle1.setDecoration(skia::textlayout::TextDecoration::kUnderline); // 添加下划线
    textStyle1.setDecorationColor(SK_ColorRED);                             // 设置下划线颜色
    builder->pushStyle(textStyle1);
    builder->addText("This is the paragraph test. ");

    // 添加占位符
    skia::textlayout::PlaceholderStyle placeholderStyle(50,                                              // 宽度
                                                        50,                                              // 高度
                                                        skia::textlayout::PlaceholderAlignment::kMiddle, // 对齐方式
                                                        skia::textlayout::TextBaseline::kAlphabetic,     // 基线类型
                                                        0);                                              // 基线偏移
    builder->addPlaceholder(placeholderStyle);

    builder->addText("\nAdding more text to test updates/Ellipsis");

    // 构建段落
    std::unique_ptr<skia::textlayout::Paragraph> paragraph = builder->Build();

    // 设置段落宽度并布局
    paragraph->layout(1000);              // 设置宽度
    paragraph->paint(&test_canvas, 0, 0); // 绘制文本到 Canvas 上
    // **测试段落的属性**
    int lineCount = paragraph->lineNumber();            // 获取段落的行数
    bool isOverflow = paragraph->didExceedMaxLines();   // 是否超出最大行数
    SkScalar longestLine = paragraph->getLongestLine(); // 获取最长行的宽度

    // 打印测试信息
    SkDebugf("Line Count: %d\n", lineCount);
    SkDebugf("Did Exceed Max Lines: %d\n", isOverflow);
    SkDebugf("Longest Line Width: %f\n", longestLine);

    // **测量文字范围并绘制矩形**
    auto rects = paragraph->getRectsForRange(0, 100, skia::textlayout::RectHeightStyle::kTight,
                                             skia::textlayout::RectWidthStyle::kTight);
    for (const auto &rect : rects) {
        SkPaint rectPaint;
        rectPaint.setColor(SK_ColorRED);
        rectPaint.setStyle(SkPaint::kStroke_Style); // 设置为描边模式
        rectPaint.setStrokeWidth(2);
        test_canvas.drawRect(rect.rect, rectPaint); // 绘制矩形范围
    }

    // **复用段落并更新样式**
    paragraph->updateFontSize(0, 10, 60); // 前两个参数没用，都是设置所有text，而且OH接口解释的貌似也不太对

    // 重新绘制更新后的段落
    paragraph->markDirty();
    paragraph->layout(1000);                // 重新布局
    paragraph->paint(&test_canvas, 0, 150); // 绘制更新后的段落

    // **测试段落的属性**
    lineCount = paragraph->lineNumber();         // 获取段落的行数
    isOverflow = paragraph->didExceedMaxLines(); // 是否超出最大行数
    longestLine = paragraph->getLongestLine();   // 获取最长行的宽度

    // 打印测试信息
    SkDebugf("Line Count: %d\n", lineCount);
    SkDebugf("Did Exceed Max Lines: %d\n", isOverflow);
    SkDebugf("Longest Line Width: %f\n", longestLine);

    // **测量文字范围并绘制矩形**
    rects = paragraph->getRectsForRange(0, 100, skia::textlayout::RectHeightStyle::kTight,
                                        skia::textlayout::RectWidthStyle::kTight);
    for (const auto &rect : rects) {
        SkRect adjustedRect =
            SkRect::MakeLTRB(rect.rect.left(), rect.rect.top() + 150, rect.rect.right(), rect.rect.bottom() + 150);

        SkPaint rectPaint;
        rectPaint.setColor(SK_ColorRED);
        rectPaint.setStyle(SkPaint::kStroke_Style); // 设置为描边模式
        rectPaint.setStrokeWidth(2);
        test_canvas.drawRect(adjustedRect, rectPaint); // 绘制矩形范围
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawText3, TEST_LEVEL::NORMAL, 500) {
    SkFont font; // default font
    font.setSize(50.0f);

    SkPaint paint;
    SkPaint measurePaint;

    SkString text1("默认字体");
    paint.setStroke(true);
    paint.setStrokeWidth(15);
    measurePaint.setStroke(true);
    measurePaint.setStrokeWidth(4);
    measurePaint.setColor(SK_ColorRED);
    SkRect textRect;

    test_canvas.drawSimpleText(text1.c_str(), text1.size(), SkTextEncoding::kUTF8, 50, 100, font, paint);
    font.measureText(text1.c_str(), text1.size(), SkTextEncoding::kUTF8, &textRect, &paint);
    textRect.offset(50, 100);
    test_canvas.drawRect(textRect, measurePaint);

    const char16_t *str16 = u"默认字体(utf-16)";
    const char32_t *str32 = U"一大复杂中1-(utf-32)";

    paint.setStyle(SkPaint::kFill_Style);
    // 创建一个模糊 MaskFilter，作为光晕/发光效果
    float blurSigma = 10.0f; // 越大越模糊、发光范围越宽
    sk_sp<SkMaskFilter> maskFilter = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, blurSigma);

    // 应用到 paint
    paint.setMaskFilter(maskFilter);

    test_canvas.drawSimpleText(str16, std::char_traits<char16_t>::length(str16) * sizeof(char16_t),
                               SkTextEncoding::kUTF16, 250, 200, font, paint);
    font.measureText(str16, std::char_traits<char16_t>::length(str16) * sizeof(char16_t), SkTextEncoding::kUTF16,
                     &textRect, &paint);
    textRect.offset(250, 200);
    test_canvas.drawRect(textRect, measurePaint);

    paint.setStyle(SkPaint::kStrokeAndFill_Style);

    test_canvas.drawSimpleText(str32, std::char_traits<char32_t>::length(str32) * sizeof(char32_t),
                               SkTextEncoding::kUTF32, 600, 200, font, paint);
    font.measureText(str32, std::char_traits<char32_t>::length(str32) * sizeof(char32_t), SkTextEncoding::kUTF32,
                     &textRect, &paint);
    textRect.offset(600, 200);
    test_canvas.drawRect(textRect, measurePaint);

    SkGlyphID str32_glyphs[100];
    int glyph_cnt = font.textToGlyphs(str32, std::char_traits<char32_t>::length(str32) * sizeof(char32_t),
                                      SkTextEncoding::kUTF32, str32_glyphs, 100);
    SkScalar gly_width[100];
    SkRect gly_rect[100];

    SkPoint point[100];
    font.getWidthsBounds(str32_glyphs, glyph_cnt, gly_width, gly_rect, &paint);
    font.getPos(str32_glyphs, glyph_cnt, point, {600, 350});
    SkScalar xpos[100];
    font.getXPos(str32_glyphs, glyph_cnt, xpos, 600);
    auto space = font.getSpacing();

    for (int i = 0; i < glyph_cnt; i++) {
        test_canvas.drawRect(
            SkRect::MakeXYWH(point[i].x(), gly_rect[i].y() + 300, gly_rect[i].width(), gly_rect[i].height()),
            measurePaint);
        test_canvas.drawRect(SkRect::MakeXYWH(gly_rect[i].x() + space * i + 600, gly_rect[i].y() + 400,
                                              gly_rect[i].width(), gly_rect[i].height()),
                             measurePaint);
    }

    auto fontMgr = SkFontMgr::RefDefault();
    // 整个绘制的生命周期里，自定义字体不能销毁，当字体销毁时，drawRecordCmd的效果会被影响，会绘制不出来
    static auto typeface2 =
        fontMgr->makeFromFile("/data/storage/el1/bundle/entry/resources/resfile/YiShanBeiZhuanTi.ttf", 0);
    static auto typeface3 =
        fontMgr->makeFromData(ReadFontData("/data/storage/el1/bundle/entry/resources/resfile/YiShanBeiZhuanTi.ttf"));
    SkFont font2(typeface2);
    SkFont font3(typeface3);
    font2.setSize(50.0f);
    font3.setSize(50.0f);

    SkUnichar chr = L'体';
    SkDebugf("glyph of '体' in default font: %u\n", font.unicharToGlyph(chr));
    SkDebugf("glyph of '体' in custom font: %u\n", font2.unicharToGlyph(chr));

    SkPaint paint2;
    SkString text2("自定义字体");
    test_canvas.drawSimpleText(text2.c_str(), text2.size(), SkTextEncoding::kUTF8, 50, 300, font2, paint2);
    font2.measureText(text2.c_str(), text2.size(), SkTextEncoding::kUTF8, &textRect, &paint2);
    textRect.offset(50, 300);
    test_canvas.drawRect(textRect, measurePaint);

    paint2.setStroke(true);
    paint2.setStrokeWidth(10);
    test_canvas.drawSimpleText(text2.c_str(), text2.size(), SkTextEncoding::kUTF8, 300, 300, font3, paint2);
    font3.measureText(text2.c_str(), text2.size(), SkTextEncoding::kUTF8, &textRect, &paint2);
    textRect.offset(300, 300);
    test_canvas.drawRect(textRect, measurePaint);
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawTextPath, TEST_LEVEL::NORMAL, 400) {
    SkFont font;
    SkPaint paint;
    SkPaint paintStroke;
    font.setSize(50.0f);

    paintStroke.setStroke(SkPaint::kStroke_Style);

    std::string utf8 = "你好,World!";
    const char* ptr = utf8.c_str();
    const char* end = ptr + utf8.size();
    test_canvas.save();
    float scale = 1.0f;
    test_canvas.translate(50, 50);
    while (ptr < end) {
        SkUnichar uni = SkUTF::NextUTF8(&ptr, end);
        if (uni < 0) break;
        auto glyphID = font.unicharToGlyph(uni);
        SkPath tmpPath;
        font.getPath(glyphID, &tmpPath);
        tmpPath.addRect(tmpPath.getBounds());
        tmpPath.transform(SkMatrix::Scale(scale, 1.0f));
        scale*=1.2;
        test_canvas.drawPath(tmpPath, paintStroke);
        test_canvas.translate(50*scale, 0);
    }
    test_canvas.restore();

    test_canvas.translate(50, 125);

    std::vector<SkUnichar> unichars;
    std::vector<SkGlyphID> glyphIDs;
    ptr = utf8.c_str();
    end = ptr + utf8.size();
    while (ptr < end) {
        SkUnichar uni = SkUTF::NextUTF8(&ptr, end);
        if (uni < 0) break;
        unichars.push_back(uni);
        glyphIDs.push_back(font.unicharToGlyph(uni));
    }

    std::vector<SkPath> paths;
    auto proc = [](const SkPath* src, const SkMatrix& mx, void* ctx) {
        auto* pathVec = static_cast<std::vector<SkPath>*>(ctx);
        if (src) {
            SkPath dst = *src;
            pathVec->push_back(dst.makeScale(1.5, 1.5));
        } else {
            pathVec->push_back(SkPath{});
        }
    };
    font.getPaths(glyphIDs.data(), glyphIDs.size(), proc, &paths);

    for (size_t i = 0; i < glyphIDs.size(); ++i) { 
        test_canvas.drawPath(paths[i], paint);
        test_canvas.translate(50, 0);
    }

    SkPath totalPath;
    int count = 1;
    for (const auto& path: paths) {
        totalPath.addPath(path, 50 * (count++), 0);
    }
    SkMatrix matrix;
    matrix.setRotate(-15);
    totalPath.transform(matrix);

    test_canvas.translate(-450, 100);
    test_canvas.drawPath(totalPath, paint);

    SkPath extraPath;
    extraPath.addRect({50, -120, 500, -40});

    SkPath totalPath1 = totalPath;
    SkPath totalPath2 = totalPath;

    test_canvas.translate(0, 100);
    paintStroke.setColor(SK_ColorGREEN);
    test_canvas.drawPath(totalPath1.addPath(extraPath), paintStroke);

    test_canvas.translate(0, 100);
    paint.setColor(SK_ColorRED);

    SkPath tmpPath = extraPath.addPath(totalPath2);
    tmpPath.setFillType(SkPathFillType::kEvenOdd);
    test_canvas.drawPath(tmpPath, paint);
}

DEF_TEST_CANVAS(drawRRRectArc, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 100.f;

    SkPaint paint;

    paint.setColor(SK_ColorBLUE);
    test_canvas.drawArc({start_X, 50, start_X + width, 200}, 0, 200, true, paint);
    start_X += width * 1.3;
    
    test_canvas.drawArc({start_X, 50, start_X + width, 200}, 0, 200, false, paint);
    start_X += width * 1.3;

    paint.setColor(SK_ColorRED);
    paint.setStroke(true);
    paint.setStrokeWidth(20);
    test_canvas.drawArc({start_X, 50, start_X + width, 200}, 30, 270, true, paint);
    start_X += width * 1.3;
    
    test_canvas.drawArc({start_X, 50, start_X + width, 200}, 30, 270, false, paint);
    start_X += width * 1.3;

    test_canvas.drawOval({start_X, 50, start_X + width, 200}, paint);
    start_X += width * 1.3;

    SkRRect rrect;
    rrect.setRectXY({start_X, 50, start_X + width, 200}, 20, 20);
    test_canvas.drawRRect(rrect, paint);
    start_X += width * 1.3;

    SkRRect rrect_outer;
    SkRRect rrect_inner;
    paint.setStroke(false);
    rrect_outer.setRectXY({start_X, 50, start_X + width, 200}, 20, 20);
    rrect_inner.setRectXY({start_X + 20, 50 + 20, start_X + width - 20, 200 - 20}, 50, 50);
    test_canvas.drawDRRect(rrect_outer, rrect_inner, paint);
    start_X += width * 1.3;
}

DEF_TEST_CANVAS(drawPathColorFilterAdvanced, TEST_LEVEL::NORMAL) {
    float start_X = 20.f;
    float width = 120.f;

    SkPaint paint;

    SkPath path1;
    path1.moveTo(start_X, 150);
    path1.quadTo(start_X + width / 2, 50, start_X + width, 150);

    paint.setColor(SkColorSetRGB(96, 64, 32));
    test_canvas.drawPath(path1, paint);
    start_X += width * 1.5;

    SkPath path2;
    path2.moveTo(start_X, 150);
    path2.conicTo(start_X + width / 2, 50, start_X + width, 150, 0.8f);

    sk_sp<SkColorFilter> color_filter2 = SkColorFilters::LinearToSRGBGamma();
    paint.setColorFilter(color_filter2);
    test_canvas.drawPath(path2, paint);
    start_X += width * 1.5;

    SkPath path3;
    path3.moveTo(start_X, 150);
    path3.cubicTo(start_X + width / 3, 50, start_X + 2 * width / 3, 250, start_X + width, 150);

    sk_sp<SkColorFilter> color_filter3 = SkColorFilters::SRGBToLinearGamma();
    paint.setColorFilter(color_filter3);
    test_canvas.drawPath(path3, paint);
    start_X += width * 1.5;

    SkPath path4;
    SkRect oval_bounds = SkRect::MakeLTRB(start_X, 100, start_X + width, 200);
    path4.addOval(oval_bounds);

    sk_sp<SkColorFilter> color_filter4 = SkLumaColorFilter::Make();
    paint.setColorFilter(color_filter4);
    test_canvas.drawPath(path4, paint);
    start_X += width * 1.5;

    SkPath path5;
    SkRect arc_bounds = SkRect::MakeLTRB(start_X, 100, start_X + width, 200);
    path5.addArc(arc_bounds, 0, 270);

    sk_sp<SkColorFilter> color_filter5 = SkColorFilters::LinearToSRGBGamma();
    paint.setColorFilter(color_filter5);
    test_canvas.drawPath(path5, paint);
    start_X += width * 1.5;

    SkPath path6;
    SkPoint points[] = {
        {start_X, 150}, {start_X + width / 2, 50}, {start_X + width, 150}, {start_X + width / 2, 250}, {start_X, 150}};
    path6.addPoly(points, 5, true);

    sk_sp<SkColorFilter> color_filter6 = SkColorFilters::SRGBToLinearGamma();
    paint.setColorFilter(color_filter6);
    test_canvas.drawPath(path6, paint);
    start_X += width * 1.5;

    SkPath path8;
    SkRect rect = SkRect::MakeLTRB(start_X, 100, start_X + width, 200);
    SkVector radii[4] = {{20, 20}, {20, 20}, {20, 20}, {20, 20}};
    SkRRect rrect;
    rrect.setRectRadii(rect, radii);
    path8.addRRect(rrect, SkPathDirection::kCCW);

    sk_sp<SkColorFilter> color_filter8 = SkColorFilters::LinearToSRGBGamma();
    paint.setColorFilter(color_filter8);
    test_canvas.drawPath(path8, paint);
    start_X += width * 1.5;

    // test for SkDashPathEffect
    SkPath path7;
    path7.addPath(path1, start_X, 0);

    SkScalar intervals[] = {10.0f, 5.0f}; // 10px "on", 5px "off"
    auto dashEffect = SkDashPathEffect::Make(intervals, 2, 0.0f);

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(5.0f);
    paint.setColorFilter(nullptr);
    paint.setShader(nullptr);
    paint.setPathEffect(dashEffect);

    test_canvas.drawPath(path7, paint);
    
    // test for Op
    SkPath path9;
    path3.offset(-width * 1.5, 0);
    Op(path2, path3, SkPathOp::kIntersect_SkPathOp, &path9);
    start_X += width * 1.5;
    path9.offset(start_X - width * 1.5, 0);
    test_canvas.drawPath(path9, paint);
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawPathWithPathEffect, TEST_LEVEL::NORMAL, 500) {
    // test for PathEffect
    SkPaint paintEffect, paint;
    paintEffect.setStyle(SkPaint::kStroke_Style);
    paintEffect.setStrokeWidth(5);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(5);
    
    auto cornerEffect = SkCornerPathEffect::Make(30); // 圆角半径为30
    paintEffect.setPathEffect(cornerEffect);
    
    SkPath path;
    path.moveTo(50, 50);
    path.lineTo(150, 50);
    path.lineTo(150, 150);
    path.lineTo(50, 150);
    path.close();
    
    test_canvas.drawPath(path, paintEffect);
    
    test_canvas.translate(150, 0);
    test_canvas.drawPath(path, paint);

    // 虚线效果
    SkScalar intervals[] = {15, 10}; // 线段长度 + 间隔
    auto dash = SkDashPathEffect::Make(intervals, 2, 0);
    
    // 组合：先圆角，再虚线
    auto composed1 = SkPathEffect::MakeCompose(dash, cornerEffect);
    paintEffect.setPathEffect(composed1);

    test_canvas.translate(150, 0);
    test_canvas.drawPath(path, paintEffect);

    // 组合：先虚线，再圆角
    auto composed2 = SkPathEffect::MakeCompose(cornerEffect, dash);
    paintEffect.setPathEffect(composed2);

    test_canvas.translate(150, 0);
    test_canvas.drawPath(path, paintEffect);

    // 构造重复的图案：一个小三角形
    SkPath stamp;
    stamp.moveTo(0, 0);
    stamp.lineTo(20, 10);
    stamp.lineTo(0, 20);
    stamp.close();
    
    auto effect = SkPath1DPathEffect::Make(stamp, 20, 0, SkPath1DPathEffect::kRotate_Style);

    paintEffect.setPathEffect(effect);
    
    SkPath basePath;
    basePath.moveTo(50, 300);
    basePath.cubicTo(150, 200, 250, 400, 350, 300); // 曲线路径

    test_canvas.translate(150, 0);
    test_canvas.drawPath(basePath, paintEffect);

    effect = SkPath1DPathEffect::Make(stamp, 20, 0, SkPath1DPathEffect::kTranslate_Style);
    paintEffect.setPathEffect(effect);
    test_canvas.translate(200, 0);
    test_canvas.drawPath(basePath, paintEffect);

    effect = SkPath1DPathEffect::Make(stamp, 20, 0, SkPath1DPathEffect::kMorph_Style);
    paintEffect.setPathEffect(effect);
    test_canvas.translate(200, 0);
    test_canvas.drawPath(basePath, paintEffect);

    test_canvas.translate(200, 0);
    test_canvas.drawPath(basePath, paint);
}

DEF_TEST_CANVAS(drawClipAdvanced, TEST_LEVEL::NORMAL) {
    // 单独绘制这个没有问题，并且不受PathDirection的影响，path转到字符串给arkts就不行了
    float cx = 150, cy = 150;   // 圆心
    float r1 = 100;             // 外大圆半径
    float r2 = 80;             // 中洞半径
    float r3 = 20;              // 中心小圆半径
    
    // 1. 创建甜甜圈路径（大圆减去中洞）
    SkPath ring;
    ring.addCircle(cx, cy, r1, SkPathDirection::kCCW);// 只要这三个圆方向互相逆向即可，对最外层的方向没有要求
    ring.addCircle(cx, cy, r2, SkPathDirection::kCW);
    
    // 2. 创建中心小黑圆
    SkPath center;
    center.addCircle(cx, cy, r3, SkPathDirection::kCCW);
    
    // 3. 合并路径
    SkPath total;
    total.addPath(ring);
    total.addPath(center);
    
    test_canvas.clipPath(total, SkClipOp::kDifference);
    
    test_canvas.drawColor(SkColorSetARGB(255, 100, 180, 255));
//    float start_X = 20.f;
//    float width = 120.f;
//    float height = 100.f;
//    SkPaint paint;
//
//    // ********* 1. Clip Rect *********
//    SkRect clipRect = SkRect::MakeLTRB(start_X, 100, start_X + width, 100 + height);
//    test_canvas.save();
//    test_canvas.clipRect(clipRect);
//
//    paint.setColor(SkColorSetARGB(255, 255, 0, 0));
//    test_canvas.drawRect(SkRect::MakeLTRB(start_X - 20, 80, start_X + width + 20, 220), paint); // 大于clip区域
//
//    test_canvas.restore();
//    // 边框
//    paint.setStyle(SkPaint::kStroke_Style);
//    paint.setColor(SkColorSetARGB(255, 0, 0, 0));
//    paint.setStrokeWidth(2);
//    test_canvas.drawRect(clipRect, paint);
//
//    start_X += width * 1.5;
//
//    // ********* 2. Clip RRect *********
//    SkRect rrectRect = SkRect::MakeLTRB(start_X, 100, start_X + width, 100 + height);
//    SkVector radii[4] = {{20,20}, {20,20}, {20,20}, {20,20}};
//    SkRRect rrect;
//    rrect.setRectRadii(rrectRect, radii);
//
//    test_canvas.save();
//    test_canvas.clipRRect(rrect);
//
//    paint.setStyle(SkPaint::kFill_Style);
//    paint.setColor(SkColorSetARGB(255, 0, 200, 255));
//    test_canvas.drawRect(SkRect::MakeLTRB(start_X - 20, 80, start_X + width + 20, 220), paint); // 超出范围
//
//    test_canvas.restore();
//    // 边框
//    paint.setStyle(SkPaint::kStroke_Style);
//    paint.setColor(SkColorSetARGB(255, 0, 0, 0));
//    test_canvas.drawRRect(rrect, paint);
//
//    start_X += width * 1.5;
//
//    // ********* 3. Clip Path (星形) *********
//    SkPath starPath;
//    float cx = start_X + width / 2;
//    float cy = 150;
//    float radius_outer = 50;
//    float radius_inner = 20;
//    int num_points = 5;
//    for (int i = 0; i < num_points * 2; ++i) {
//        float angle = float(i) * SK_ScalarPI / num_points;
//        float r = (i % 2 == 0) ? radius_outer : radius_inner;
//        float x = cx + r * cosf(angle);
//        float y = cy + r * sinf(angle);
//        if (i == 0)
//            starPath.moveTo(x, y);
//        else
//            starPath.lineTo(x, y);
//    }
//    starPath.close();
//
//    test_canvas.save();
//    test_canvas.clipPath(starPath);
//
//    paint.setStyle(SkPaint::kFill_Style);
//    paint.setColor(SkColorSetARGB(255, 120, 255, 120));
//    test_canvas.drawOval(SkRect::MakeLTRB(start_X - 20, 100, start_X + width + 20, 200), paint);
//
//    test_canvas.restore();
//    // 边框
//    paint.setStyle(SkPaint::kStroke_Style);
//    paint.setColor(SkColorSetARGB(255, 0, 0, 0));
//    test_canvas.drawPath(starPath, paint);
//
//    // 4. 多重clip
//    start_X += width * 1.5;
//    SkRect multiClipRect = SkRect::MakeLTRB(start_X, 100, start_X + width, 200);
//    
//    float multi_cx = start_X + width * 0.2f;
//    float multi_cy = 150;
//    float multi_radius_outer = 60;
//    float multi_radius_inner = 25;
//    int multi_num_points = 5;
//    
//    SkPath multiStarPath;
//    for (int i = 0; i < multi_num_points * 2; ++i) {
//        float angle = float(i) * SK_ScalarPI / multi_num_points;
//        float r = (i % 2 == 0) ? multi_radius_outer : multi_radius_inner;
//        float x = multi_cx + r * cosf(angle);
//        float y = multi_cy + r * sinf(angle);
//        if (i == 0)
//            multiStarPath.moveTo(x, y);
//        else
//            multiStarPath.lineTo(x, y);
//    }
//    multiStarPath.close();
//    
//    test_canvas.save();
//    test_canvas.clipRect(multiClipRect);
//    test_canvas.clipPath(multiStarPath);
//    
//    paint.setStyle(SkPaint::kFill_Style);
//    paint.setColor(SkColorSetARGB(180, 255, 0, 255)); // 半透明洋红
//    test_canvas.drawRect(SkRect::MakeLTRB(start_X - 40, 80, start_X + width + 40, 220), paint);
//    
//    test_canvas.restore();
//    
//    // 边框辅助
//    paint.setStyle(SkPaint::kStroke_Style);
//    paint.setColor(SkColorSetARGB(255, 0, 0, 0));
//    paint.setStrokeWidth(2);
//    test_canvas.drawRect(multiClipRect, paint);
//    test_canvas.drawPath(multiStarPath, paint);
}

sk_sp<SkPicture> gSkPicture1 = nullptr;
sk_sp<SkPicture> gSkPicture2 = nullptr;
sk_sp<SkPicture> gSkPicture3 = nullptr;

static void createSkPicture() {
    if (gSkPicture1) {
        return;
    }
    SkPictureRecorder recorder;

    SkRect rect = SkRect::MakeLTRB(-(1<<30), -(1<<30), (1<<30) - 1, (1<<30) - 1);
    SkCanvas *recordCanvas = recorder.beginRecording(rect);
//    SkCanvas *recordCanvas = recorder.beginRecording(1000, 1000);

    recordCanvas->translate(-100, 0);
    TestCanvas_drawPathColorFilterAdvanced(*recordCanvas);
    gSkPicture1 = recorder.finishRecordingAsPicture();

    recordCanvas = recorder.beginRecording(500, 500);
    TestCanvas_drawText(*recordCanvas);
    recordCanvas->translate(0, 200);
    recordCanvas->drawPicture(gSkPicture1);

    gSkPicture2 = recorder.finishRecordingAsPicture();
    
    SkPictureRecorder recorder3;
    SkCanvas* recordCanvas3 = recorder3.beginRecording(rect);

//    SkPaint paint;
//    paint.setColor(SkColorSetARGB(255, 100, 180, 255)); // 淡蓝
    recordCanvas3->drawColor(SkColorSetARGB(255, 100, 180, 255));
//    recordCanvas3->drawRect(SkRect::MakeLTRB(50, 50, 350, 350), paint);

    gSkPicture3 = recorder3.finishRecordingAsPicture();
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawPicture, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    SkPaint paint;
    paint.setAlphaf(0.3);
    test_canvas.clear(SkColorSetRGB(200, 200, 200));
    SkPaint paint1;
    paint1.setColor(SK_ColorGREEN);
//    test_canvas.drawRect({-50, -50, 300, 300}, paint1);

    test_canvas.drawPicture(gSkPicture1);
    paint1.setColor(SK_ColorBLUE);
    test_canvas.drawRect({-50, -50, 300, 300}, paint1);
    paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({50, 50, 250, 150}, paint1);
    test_canvas.clipRect({0, 0, 3000, 350});
    test_canvas.translate(1500, 0);
    test_canvas.drawPicture(gSkPicture2);
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawPictureWithSaveLayer, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    SkPaint paint;
    paint.setAlphaf(0.1);
    test_canvas.saveLayer({0, 0, 3000, 400}, &paint);
    test_canvas.clear(SkColorSetRGB(200, 200, 200));
    SkPaint paint1;
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawRect({-50, -50, 300, 300}, paint1);

    test_canvas.drawPicture(gSkPicture1);
    test_canvas.translate(1500, 0);
    paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({50, 50, 250, 150}, paint1);
    test_canvas.drawPicture(gSkPicture2);
    test_canvas.restore();
}

// need OH_Drawing_CanvasDrawRecordCmdNesting system support
DEF_TEST_CANVAS_WITH_HEIGHT(drawPictureWithPaintMatirx, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    SkPaint paint;
    paint.setAlphaf(0.3);

    test_canvas.clear(SkColorSetRGB(200, 200, 200));

    SkMatrix m;
    m.preScale(0.5, 0.5);
    m.preRotate(30);

    test_canvas.drawPicture(gSkPicture1, &m, &paint);
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest1_BasicSaveRestore, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // 普通绘制指令 (不会触发子canvas)
    SkPaint paint1;
    paint1.setColor(SK_ColorBLUE);
    test_canvas.drawRect({10, 10, 100, 100}, paint1);
    
    // drawpicture (让子canvas进入预备态)
    test_canvas.drawPicture(gSkPicture1);
    
    // 普通绘制指令 (触发创建子canvas并开始录制)
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawRect({120, 10, 220, 100}, paint1);
    test_canvas.drawCircle({170, 55}, 30, paint1);
    
    // save指令 (在子canvas中执行)
    int saveCount = test_canvas.save();
    test_canvas.translate(1500, 0);
    
    // drawpicture (仍然在子canvas中绘制，但挂载到一个新节点上)
    test_canvas.clipRect({50, 50, 700, 200}); 
    test_canvas.drawPicture(gSkPicture3);
    
    // 普通绘制指令，新建一个子canvas进行绘制
    paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({400, 50, 500, 150}, paint1);
    test_canvas.drawOval({450, 75, 550, 125}, paint1);
    
    // restore (结束子canvas)
    test_canvas.restore();
    
    // 额外的绘制来验证状态正确性
    paint1.setColor(SK_ColorYELLOW);
    test_canvas.drawRect({600, 10, 800, 150}, paint1);
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest1_BasicSaveRestore2, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // 普通绘制指令 (不会触发子canvas)
    SkPaint paint1;
    paint1.setColor(SK_ColorBLUE);
    test_canvas.drawRect({10, 10, 100, 100}, paint1);
    
    // drawpicture (让子canvas进入预备态)
    test_canvas.drawPicture(gSkPicture1);
    
    // 普通绘制指令 (触发创建子canvas并开始录制)
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawRect({120, 10, 220, 100}, paint1);
    
    // save指令 (在子canvas中执行)
    int saveCount = test_canvas.save();
    test_canvas.translate(1500, 0);
    
    // drawpicture (仍然在子canvas中绘制，但挂载到一个新节点上)
    test_canvas.drawPicture(gSkPicture3);
    
    // 普通绘制指令，新建一个子canvas进行绘制
    paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({400, 50, 500, 150}, paint1);
    test_canvas.drawOval({450, 75, 550, 125}, paint1);
    
    // restore (结束子canvas)
    test_canvas.restore();
    
    // 额外的绘制来验证状态正确性
    paint1.setColor(SK_ColorYELLOW);
    test_canvas.drawRect({600, 10, 800, 150}, paint1);
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest2_NestedSaveRestore, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // drawpicture (让子canvas进入预备态)
    test_canvas.drawPicture(gSkPicture1);
    
    // 普通绘制指令 (触发创建子canvas)
    SkPaint paint1;
    paint1.setColor(SK_ColorCYAN);
    test_canvas.drawRect({50, 50, 150, 150}, paint1);
    
    // 多层save/restore嵌套 (都在子canvas中)
    int saveCount1 = test_canvas.save();
    test_canvas.scale(1.2f, 1.2f);
    paint1.setColor(SK_ColorMAGENTA);
    test_canvas.drawRect({200, 50, 280, 130}, paint1);
    
    int saveCount2 = test_canvas.save();
    test_canvas.rotate(15);
    paint1.setColor(SK_ColorGRAY);
    test_canvas.drawRect({320, 50, 400, 130}, paint1);
    
    int saveCount3 = test_canvas.save();
    test_canvas.translate(100, 50);
    paint1.setColor(SK_ColorBLACK);
    test_canvas.drawCircle({50, 50}, 25, paint1);
    
    paint1.setColor(SK_ColorWHITE);
    test_canvas.drawRect({0, 0, 40, 40}, paint1);
    
    // restoreToCount恢复到最开始
    test_canvas.restoreToCount(saveCount1);
    
    // 验证状态恢复
    paint1.setColor(SK_ColorLTGRAY);
    test_canvas.drawRect({500, 50, 600, 150}, paint1);
    
    // drawpicture (结束子canvas录制)
    test_canvas.clipRect({50, 50, 300, 300});
    test_canvas.drawPicture(gSkPicture3);
    
    // 普通绘制指令 (在新的子canvas中)
    paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({650, 50, 750, 150}, paint1);
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest3_CrossBoundarySave, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // 普通绘制指令 (不会触发子canvas)
    SkPaint paint1;
    paint1.setColor(SK_ColorDKGRAY);
    test_canvas.drawRect({0, 0, 80, 80}, paint1);
    
    // save指令 (在主canvas上)
    int initialSaveCount = test_canvas.save();
    test_canvas.translate(100, 0);
    test_canvas.scale(0.8f, 0.8f);
    
    // drawpicture (子canvas进入预备态)
    test_canvas.drawPicture(gSkPicture1);
    
    // 普通绘制指令 (触发子canvas创建)
    paint1.setColor(SK_ColorLTGRAY);
    test_canvas.drawRect({150, 20, 250, 120}, paint1);
    
    // 多层save/restore嵌套 (在子canvas中)
    int saveCount1 = test_canvas.save();
    test_canvas.translate(150, 0);
    
    SkPaint layerPaint;
    layerPaint.setAlphaf(0.7f);
    int saveCount2 = test_canvas.saveLayer({0, 0, 200, 200}, &layerPaint);
    
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawRect({300, 30, 400, 130}, paint1);
    
    int saveCount3 = test_canvas.save();
    test_canvas.rotate(30);
    paint1.setColor(SK_ColorBLUE);
    test_canvas.drawOval({50, 50, 150, 100}, paint1);
    
    // 添加更多绘制
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawCircle({100, 75}, 20, paint1);
    
    // restoreToCount直接恢复到最开始的状态 (跨越子canvas边界)
    test_canvas.restoreToCount(initialSaveCount);
    
    // 验证主canvas状态恢复
    paint1.setColor(SK_ColorYELLOW);
    test_canvas.drawRect({500, 10, 600, 110}, paint1);
     paint1.setColor(SK_ColorRED);
    test_canvas.drawRect({650, 10, 750, 110}, paint1);
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest_ClipDifferenceValidation, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // 首先绘制picture，让子canvas进入预备态
    test_canvas.drawPicture(gSkPicture1);
    
    SkPaint paint;
    int initialSaveCount = test_canvas.getSaveCount();
    
    // === 第一次绘制 (绿色) ===
    test_canvas.save();
    paint.setColor(SK_ColorGREEN);
    test_canvas.drawRect({50, 50, 150, 150}, paint);
    test_canvas.translate(200, 0); // 向右平移200
    
    // === 第二次绘制 (红色，包含clip difference测试) ===
    test_canvas.save();
    paint.setColor(SK_ColorRED);
    // 第一个红色矩形 (正常绘制)
    test_canvas.drawRect({50, 50, 150, 150}, paint);
//        test_canvas.clipRect({100, 60, 250, 140});

    // 设置clipRect difference - 这个区域会被"挖空"
    // 选择一个与两个矩形都有交集的区域
    SkRect clipDiffRect = {120, 80, 220, 120}; // 跨越两个矩形
    test_canvas.clipRect(clipDiffRect, SkClipOp::kDifference);
    
    // 第二个红色矩形 (受clip difference影响)
    test_canvas.drawRect({170, 50, 270, 150}, paint);
    
    test_canvas.translate(300, 0); // 向右平移200
    
    // === 第三次绘制 (绿色) ===
    test_canvas.save();
    paint.setColor(SK_ColorGREEN);
    test_canvas.drawRect({50, 50, 150, 150}, paint);
    test_canvas.translate(200, 0); // 向右平移200
    
    // === 第四次绘制 (绿色) ===
    test_canvas.save();
    paint.setColor(SK_ColorGREEN);
    test_canvas.drawRect({50, 50, 150, 150}, paint);
    test_canvas.translate(200, 0); // 向右平移200
    
    // === 恢复所有save状态 ===
    test_canvas.restoreToCount(initialSaveCount);

    test_canvas.translate(1500, 0);
    test_canvas.clipRect(clipDiffRect, SkClipOp::kDifference);
    test_canvas.drawPicture(gSkPicture2);
    
    // === 最后绘制一个矩形验证状态恢复 ===
    paint.setColor(SK_ColorBLUE);
    test_canvas.drawRect({950, 50, 1050, 150}, paint); // 最右边的蓝色矩形
}

DEF_TEST_CANVAS_WITH_HEIGHT(subCanvasTest5_Overlap, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    
    // 普通绘制指令 (不会触发子canvas)
    SkPaint paint1;
    paint1.setColor(SK_ColorBLUE);
    test_canvas.drawRect({10, 10, 100, 100}, paint1);
    
    // drawpicture (让子canvas进入预备态)
    test_canvas.drawPicture(gSkPicture1);

    test_canvas.translate(1500, 0);
    
    // 无重叠，无需创建新node
    test_canvas.drawRect({50, 50, 200, 200}, paint1);
    
    test_canvas.drawRect({250, 50, 400, 200}, paint1);

    test_canvas.drawRect({450, 50, 600, 200}, paint1);

    SkFont font; // default font
    font.setSize(30.0f);
    SkString text1("默认字体");
    test_canvas.drawSimpleText(text1.c_str(), text1.size(), SkTextEncoding::kUTF8, 650, 100, font, paint1);

    paint1.setColor(SK_ColorBLACK);

    // 有重叠，创建新的node
    test_canvas.drawRect({500, 100, 550, 150}, paint1);

}

DEF_TEST_CANVAS_WITH_HEIGHT(drawPictureWithCull, TEST_LEVEL::NORMAL, 400) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(200, 200, 200));

    SkPaint paint1;
    paint1.setColor(SK_ColorGREEN);
    test_canvas.drawRect({10, 10, 350, 350}, paint1);

    test_canvas.clipRect({10, 10, 350, 350});

    test_canvas.drawPicture(gSkPicture1);
}

// 1. clipRect测试
DEF_TEST_CANVAS(drawPictureClipRect, TEST_LEVEL::NORMAL) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(240, 240, 240));
    SkPaint paint1;
//    paint1.setColor(SK_ColorGREEN);
//    test_canvas.drawRect({99, 99, 302, 302}, paint1);

    // 只允许中间部分显示
    test_canvas.clipRect(SkRect::MakeLTRB(100, 100, 250, 250));

    test_canvas.drawPicture(gSkPicture3);
}

// 2. clipRRect测试
DEF_TEST_CANVAS(drawPictureClipRRect, TEST_LEVEL::NORMAL) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(240, 240, 240));

    SkRect rect = SkRect::MakeLTRB(100, 100, 300, 300);
    SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}};
    SkRRect rrect;
    rrect.setRectRadii(rect, radii);

    test_canvas.clipRRect(rrect);

    test_canvas.drawPicture(gSkPicture3);
}

DEF_TEST_CANVAS(drawPictureClipPath, TEST_LEVEL::NORMAL) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(240, 240, 240));

    SkPath starPath;
    float cx = 200, cy = 200, r_outer = 100, r_inner = 40;
    int num_points = 5;
    // 外层五角星（顺时针）
    for (int i = 0; i < num_points * 2; ++i) {
        float angle = i * SK_ScalarPI / num_points;
        float r = (i % 2 == 0) ? r_outer : r_inner;
        float x = cx + r * cosf(angle);
        float y = cy + r * sinf(angle);
        if (i == 0) starPath.moveTo(x, y);
        else        starPath.lineTo(x, y);
    }
    starPath.close();

    // 内层小五角星（逆时针，做洞）
    float r_outer2 = 55, r_inner2 = 23; // 控制小星的大小
    SkPath smallStar;
    for (int i = 0; i < num_points * 2; ++i) {
        float angle = -i * SK_ScalarPI / num_points; // 逆时针
        float r = (i % 2 == 0) ? r_outer2 : r_inner2;
        float x = cx + r * cosf(angle);
        float y = cy + r * sinf(angle);
        if (i == 0) smallStar.moveTo(x, y);
        else        smallStar.lineTo(x, y);
    }
    smallStar.close();

    // 把小星洞加进大星路径（作为逆向子路径）
    starPath.addPath(smallStar);

//    SkPath reversePath;
//    reversePath.reverseAddPath(starPath);

    // !!! @NOTE: If we use reversePath as clip, the clip will not work
    test_canvas.clipPath(starPath, SkClipOp::kDifference);

    test_canvas.drawPicture(gSkPicture3);
}

// Bad Clip Case，如果把方向都取反就能正常clip
DEF_TEST_CANVAS(drawPictureClipCircle, TEST_LEVEL::NORMAL) {
    createSkPicture();
    test_canvas.clear(SkColorSetRGB(240, 240, 240));

    float cx = 150, cy = 150;   // 圆心
    float r1 = 100;             // 外大圆半径
    float r2 = 80;             // 中洞半径
    float r3 = 20;              // 中心小圆半径
    
    SkPath ring;
    ring.addCircle(cx, cy, r1, SkPathDirection::kCCW);   // 外圈逆时针
    ring.addCircle(cx, cy, r2, SkPathDirection::kCW);  // 内圈顺时针，挖洞
    
    SkPath center;
    center.addCircle(cx, cy, r3, SkPathDirection::kCCW);
    
    // 3. 合并路径
    SkPath total;
    total.addPath(ring);
    total.addPath(center);
    
    test_canvas.clipPath(total, SkClipOp::kDifference);

    test_canvas.drawPicture(gSkPicture3);
}

DEF_TEST_CANVAS_WITH_HEIGHT(drawShadow, TEST_LEVEL::NORMAL, 400) {

    SkPaint paint;
    paint.setColor(SK_ColorBLUE); // 物体颜色

    SkRect rect = SkRect::MakeXYWH(100, 100, 200, 200);
    SkPath path;
    path.addRect(rect); // 创建矩形路径

    SkPoint3 zPlaneParams = {0, 0, 100};  // 物体 Z 轴高度
    SkPoint3 lightPos = {0, 0, 500}; // 光源位置（影响阴影方向）
    SkScalar lightRadius = 300;           // 光源半径（影响模糊程度）


    SkColor inAmbientColor = SkColorSetARGB(150, 255, 0, 0); // 环境阴影
    SkColor inSpotColor = SkColorSetARGB(255, 0, 255, 0);    // 点光源阴影

    SkColor ambientColor, spotColor;
    SkShadowUtils::ComputeTonalColors(inAmbientColor, inSpotColor, &ambientColor, &spotColor);

    SkShadowUtils::DrawShadow(&test_canvas, path, zPlaneParams, lightPos, lightRadius, ambientColor, spotColor, 0);
    test_canvas.drawPath(path, paint);

    // @todo: The flags seem to be no effect. Need to find the correct effect.
    SkPath path1;
    path1.addRect(SkRect::MakeXYWH(400, 100, 200, 200)); // 创建矩形路径
    SkShadowUtils::DrawShadow(&test_canvas, path1, zPlaneParams, {400, 150, 2000}, lightRadius, ambientColor, spotColor,
                              kGeometricOnly_ShadowFlag);
    test_canvas.drawPath(path1, paint);

    SkPath path2;
    path2.setFillType(SkPathFillType::kEvenOdd);
    path2.addRect(SkRect::MakeXYWH(700, 100, 200, 200)); // 创建矩形路径
    path2.addRect(SkRect::MakeXYWH(750, 150, 200, 200)); // 创建矩形路径
    SkShadowUtils::DrawShadow(&test_canvas, path2, zPlaneParams, {700, 150, 2000}, lightRadius, ambientColor, spotColor,
                              kTransparentOccluder_ShadowFlag);
    test_canvas.drawPath(path2, paint);

    // kConcaveBlurOnly_ShadowFlag/kDirectionalLight_ShadowFlag is not support

    SkPath path4;
    path4.addRect(SkRect::MakeXYWH(1100, 100, 200, 200));
    SkShadowUtils::DrawShadow(&test_canvas, path4, zPlaneParams, {1100, 150, 2000}, lightRadius, inAmbientColor,
                              inSpotColor, kAll_ShadowFlag);
    test_canvas.drawPath(path4, paint);
    
    // kDirectionalLight_ShadowFlag is support now
    SkPath path5;
    path5.addRect(SkRect::MakeXYWH(1500, 100, 200, 200));
    SkShadowUtils::DrawShadow(&test_canvas, path5, zPlaneParams, {1100, 150, 2000}, lightRadius, inAmbientColor,
                              inSpotColor, 0);
    paint.setColor(SkColorSetARGB(128, 0, 0, 255)); // 物体颜色
    test_canvas.drawPath(path5, paint);
}

static void TraverseDOM(const SkDOM &dom, const SkDOM::Node *node, int depth = 0) {
    if (!node)
        return;

    // 打印缩进（用于显示层级结构
    std::string space = "";
    for (int i = 0; i < depth; i++)
        space += "  ";

    // 获取标签名称
    const char *tagName = dom.getName(node);
    if (!tagName || strlen(tagName) == 0 || tagName[0] == '\n')
        return;
    LOGI((space + "Tag: %{public}s\n").c_str(), tagName);

    // 遍历所有属性
    const char *attrName;
    const char *attrValue;
    SkDOM::AttrIter attrIter(dom, node);
    while ((attrName = attrIter.next(&attrValue))) {
        for (int i = 0; i < depth + 1; i++)
            printf("  ");
        LOGI((space + "Attribute: %{public}s = %{public}s\n").c_str(), attrName, attrValue);
    }

    // 递归遍历子节点
    for (const SkDOM::Node *child = dom.getFirstChild(node); child; child = dom.getNextSibling(child)) {
        TraverseDOM(dom, child, depth + 1);
    }
}

DEF_TEST_CANVAS_WITH_HEIGHT(printXML, TEST_LEVEL::NORMAL, 0) {
    SkDynamicMemoryWStream stream;
    SkXMLStreamWriter xmlWriter(&stream);

    xmlWriter.startElement("root");
    xmlWriter.addAttribute("version", "1.0");

    xmlWriter.startElement("child");
    char data[] = "Hello Skia XML";
    xmlWriter.addText(data, strlen(data));
    xmlWriter.endElement();
    xmlWriter.endElement();

    stream.flush();
    sk_sp<SkData> skData = stream.detachAsData();
    SkString result(reinterpret_cast<const char *>(skData->data()), skData->size());
    LOGI("xml output: \n%{public}s\n", result.c_str()); // 输出 XML

    const char *svgXml = R"end(
<svg width="400" height="400" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg">
    <!-- 定义线性渐变 -->
    <defs>
        <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" style="stop-color:rgb(255,0,0); stop-opacity:1" />
            <stop offset="100%" style="stop-color:rgb(0,0,255); stop-opacity:1" />
        </linearGradient>

        <radialGradient id="grad2" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
            <stop offset="0%" style="stop-color:rgb(255,255,0); stop-opacity:1" />
            <stop offset="100%" style="stop-color:rgb(0,128,0); stop-opacity:1" />
        </radialGradient>
    </defs>

    <!-- 透明度矩形 -->
    <rect x="10" y="10" width="100" height="100" fill="url(#grad1)" opacity="0.7" />

    <!-- 旋转 + 缩放的路径 -->
    <g transform="rotate(30 200 200) scale(1.2)">
        <path d="M150 50 L250 150 L150 250 L50 150 Z" fill="url(#grad2)" stroke="black" stroke-width="5"/>
    </g>

    <!-- 圆形 -->
    <circle cx="300" cy="100" r="50" fill="purple" stroke="black" stroke-width="3" opacity="0.6"/>

    <!-- 透明度 + 变换的文本 -->
    <text x="50" y="300" font-size="30" fill="black" transform="skewX(-20)">Hello, SVG!</text>

    <!-- 复杂路径 -->
    <path d="M20,350 Q120,250 220,350 T420,350" fill="none" stroke="blue" stroke-width="5" />
</svg>)end";

    SkDOM skdom;
    SkMemoryStream svgStream(svgXml, strlen(svgXml), false);
    skdom.build(svgStream);

    // 获取根节点
    const SkDOM::Node *root = skdom.getRootNode();
    if (root) {
        TraverseDOM(skdom, root);
    }
}

static std::vector<sk_sp<SkSVGDOM>> gAllSVGs;

static void PrepareSVGs() {
    const char *svgXml = R"end(
<svg width="500" height="500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
    <!-- 定义渐变 -->
    <defs>
        <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" style="stop-color: red; stop-opacity: 1" />
            <stop offset="100%" style="stop-color: blue; stop-opacity: 1" />
        </linearGradient>

        <radialGradient id="grad2" cx="50%" cy="50%" r="50%">
            <stop offset="0%" style="stop-color: yellow; stop-opacity: 1" />
            <stop offset="100%" style="stop-color: green; stop-opacity: 1" />
        </radialGradient>

        <!-- 定义图案 -->
        <pattern id="pattern1" patternUnits="userSpaceOnUse" width="10" height="10">
            <circle cx="5" cy="5" r="3" fill="black" />
        </pattern>

        <!-- 定义滤镜 -->
        <filter id="blurFilter">
            <feGaussianBlur stdDeviation="4" />
        </filter>

        <!-- 定义剪切路径 -->
        <clipPath id="clip1">
            <rect x="50" y="50" width="100" height="100" />
        </clipPath>
    </defs>

    <!-- 矩形 -->
    <rect x="10" y="10" width="100" height="100" fill="url(#grad1)" stroke="black" stroke-width="2" />

    <!-- 圆形 -->
    <circle cx="200" cy="60" r="50" fill="url(#grad2)" stroke="black" stroke-width="2" />

    <!-- 椭圆 -->
    <ellipse cx="350" cy="60" rx="60" ry="40" fill="purple" stroke="black" stroke-width="2" />

    <!-- 直线 -->
    <line x1="10" y1="200" x2="150" y2="200" stroke="black" stroke-width="3" />

    <!-- 多边形 -->
    <polygon points="200,150 250,200 200,250 150,200" fill="orange" stroke="black" stroke-width="2" />
    <polygon points="100,20 180,80 150,160 50,160 20,80" fill="orange" stroke="black" stroke-width="3"/>
    <polygon points="100,30 170,60 170,120 100,150 30,120 30,60" fill="green" fill-opacity="0.5" stroke="black"/>

    <!-- 路径 -->
    <path d="M300 150 Q350 100 400 150 T500 150" fill="none" stroke="blue" stroke-width="3" />

    <!-- 使用剪切路径 -->
    <!-- <rect x="50" y="50" width="150" height="150" fill="url(#pattern1)" clip-path="url(#clip1)" /> -->

    <!-- 带滤镜的矩形 -->
    <rect x="300" y="300" width="100" height="100" fill="green" filter="url(#blurFilter)" />

    <!-- 变换 -->
    <g transform="rotate(30 400 400) scale(1.2)">
        <rect x="350" y="350" width="100" height="100" fill="pink" stroke="black" stroke-width="2" />
    </g>

    <!-- 文本 -->
      <!--<text x="50" y="350" font-family="Arial" font-size="24" fill="black">Hello, SVG!</text>-->

    <!-- 半透明矩形 -->
    <rect x="50" y="400" width="100" height="50" fill="blue" opacity="0.5" />

    <!-- 使用 pattern 作为填充 -->
    <!-- <rect x="200" y="400" width="100" height="50" fill="url(#pattern1)" /> -->
</svg>
)end";

    SkMemoryStream svgStream1(svgXml, strlen(svgXml), true);
    auto svgDom = SkSVGDOM::MakeFromStream(svgStream1);

    gAllSVGs.push_back(svgDom);

    svgXml = R"end(
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
    <g clip-path="url(#clip0_891_107032)">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M11.7408 3.59792 11.6079 5.666H14.6146C15.6247 5.666 16.3841 6.705 16.2313 7.73849L16.2114 7.84915 15.1398 12.9071C14.9809 13.6515 14.3747 14.1919 13.6572 14.244L13.543 14.2482 3.26257 14.2443C2.84847 14.2439 2.51285 13.9081 2.51257 13.494V7.05887C2.51257 6.64465 2.84836 6.30887 3.26257 6.30887H5.09348L6.03993 6.28657 6.35279 6.27278 6.47863 6.26195 6.49985 6.25824C7.51623 6.02181 8.29243 4.45341 8.43496 3.05094L8.4427 2.93096 8.45901 2.50164 8.47561 2.29534C8.53057 1.76443 8.69993 1.14032 9.28593.883111 10.8262.207038 11.8253 2.25924 11.7408 3.59792zM9.64765 1.70722C9.52781 1.75983 9.43631 1.92816 9.38854 2.24267L9.37271 2.36752 9.35836 2.53582 9.34083 2.98887 9.33035 3.14193C9.14089 5.0061 8.1193 6.80555 6.70377 7.13483L6.6308 7.14845 6.47843 7.16529 6.34227 7.17456 6.15007 7.182V13.3455L13.5104 13.3488 13.5919 13.3464C13.8784 13.3256 14.1331 13.1182 14.2339 12.8145L14.2594 12.7206 15.3256 7.68994 15.341 7.60687C15.4151 7.10592 15.0754 6.62591 14.6878 6.57118L14.6146 6.566H10.6482L10.8426 3.54119C10.9112 2.45485 10.1953 1.46684 9.64765 1.70722zM5.25007 7.20525 5.09348 7.20887 3.41182 7.20825V13.344L5.25007 13.3448V7.20525z" fill="#000" fill-opacity=".9"/>
    </g>
    <defs>
        <clipPath id="clip0_891_107032">
            <path d="M0 0h18v18H0z" fill="#fff"/>
        </clipPath>
    </defs>
</svg>
)end";
    SkMemoryStream svgStream2(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream2);
    gAllSVGs.push_back(svgDom);


    svgXml = R"end(
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_906_96386)"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.7494 3.55121 11.6079 5.66601H14.6663C15.507 5.66601 16.3678 6.57462 16.2349 7.69419L16.2147 7.80429 15.1652 12.8086C14.9862 13.6557 14.3851 14.1921 13.6572 14.2441L13.5414 14.2482 6.76254 14.2439C6.34851 14.2431 6.01302 13.9074 6.01254 13.4934V6.9304C6.01253 6.6358 6.19545 6.37582 6.46518 6.27301L6.54861 6.247C7.50133 6.01339 8.29036 4.44638 8.43496 3.05095L8.44281 2.93158 8.45936 2.50442 8.4762 2.29916C8.53196 1.77092 8.68955 1.107 9.28407.85109 10.8468.178418 11.8352 2.21927 11.7494 3.55121zM4.1361 14.2449 3.2641 14.2467C2.87947 14.2475 2.56188 13.9586 2.5178 13.5857L2.51257 13.4967v0V7.0621C2.51257 6.64889 2.84679 6.31352 3.26 6.3121L4.132 6.30911C4.51663 6.30779 4.83462 6.59623 4.87922 6.96909L4.88457 7.05911v0V13.4949C4.88457 13.9085 4.54971 14.2441 4.1361 14.2449z" fill="#000" fill-opacity=".9"/></g><defs><clipPath id="clip0_906_96386"><path d="M0 0h18v18H0z" fill="#fff"/></clipPath></defs></svg>
)end";
    SkMemoryStream svgStream3(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream3);
    gAllSVGs.push_back(svgDom);

    svgXml = R"end(
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
    
    <title>comment-3</title>
    <desc>Created with Sketch Beta.</desc>
    <defs>

</defs>
    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
        <g id="Icon-Set" sketch:type="MSLayerGroup" transform="translate(-204.000000, -255.000000)" fill="#000000">
            <path d="M228,267 C226.896,267 226,267.896 226,269 C226,270.104 226.896,271 228,271 C229.104,271 230,270.104 230,269 C230,267.896 229.104,267 228,267 L228,267 Z M220,281 C218.832,281 217.704,280.864 216.62,280.633 L211.912,283.463 L211.975,278.824 C208.366,276.654 206,273.066 206,269 C206,262.373 212.268,257 220,257 C227.732,257 234,262.373 234,269 C234,275.628 227.732,281 220,281 L220,281 Z M220,255 C211.164,255 204,261.269 204,269 C204,273.419 206.345,277.354 210,279.919 L210,287 L217.009,282.747 C217.979,282.907 218.977,283 220,283 C228.836,283 236,276.732 236,269 C236,261.269 228.836,255 220,255 L220,255 Z M212,267 C210.896,267 210,267.896 210,269 C210,270.104 210.896,271 212,271 C213.104,271 214,270.104 214,269 C214,267.896 213.104,267 212,267 L212,267 Z M220,267 C218.896,267 218,267.896 218,269 C218,270.104 218.896,271 220,271 C221.104,271 222,270.104 222,269 C222,267.896 221.104,267 220,267 L220,267 Z" id="comment-3" sketch:type="MSShapeGroup">

</path>
        </g>
    </g>
</svg>
)end";
    SkMemoryStream svgStream4(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream4);
    gAllSVGs.push_back(svgDom);

    svgXml = R"end(
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.5 11C9.32843 11 10 10.3284 10 9.5C10 8.67157 9.32843 8 8.5 8C7.67157 8 7 8.67157 7 9.5C7 10.3284 7.67157 11 8.5 11Z" fill="#0F0F0F"/>
<path d="M17 9.5C17 10.3284 16.3284 11 15.5 11C14.6716 11 14 10.3284 14 9.5C14 8.67157 14.6716 8 15.5 8C16.3284 8 17 8.67157 17 9.5Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.2 13C7.56149 13 6.9436 13.5362 7.01666 14.2938C7.06054 14.7489 7.2324 15.7884 7.95483 16.7336C8.71736 17.7313 9.99938 18.5 12 18.5C14.0006 18.5 15.2826 17.7313 16.0452 16.7336C16.7676 15.7884 16.9395 14.7489 16.9833 14.2938C17.0564 13.5362 16.4385 13 15.8 13H8.2ZM9.54387 15.5191C9.41526 15.3509 9.31663 15.1731 9.2411 15H14.7589C14.6834 15.1731 14.5847 15.3509 14.4561 15.5191C14.0981 15.9876 13.4218 16.5 12 16.5C10.5782 16.5 9.90187 15.9876 9.54387 15.5191Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 23C18.0751 23 23 18.0751 23 12C23 5.92487 18.0751 1 12 1C5.92487 1 1 5.92487 1 12C1 18.0751 5.92487 23 12 23ZM12 20.9932C7.03321 20.9932 3.00683 16.9668 3.00683 12C3.00683 7.03321 7.03321 3.00683 12 3.00683C16.9668 3.00683 20.9932 7.03321 20.9932 12C20.9932 16.9668 16.9668 20.9932 12 20.9932Z" fill="#0F0F0F"/>
</svg>)end";
    SkMemoryStream svgStream5(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream5);
    gAllSVGs.push_back(svgDom);

    svgXml = R"end(
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 73 73" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    
    <title>team-collaboration/version-control/github</title>
    <desc>Created with Sketch.</desc>
    <defs>

</defs>
    <g id="team-collaboration/version-control/github" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <g id="container" transform="translate(2.000000, 2.000000)" fill-rule="nonzero">
            <rect id="mask" stroke="#000000" stroke-width="2" fill="#000000" x="-1" y="-1" width="71" height="71" rx="14">

</rect>
            <path d="M58.3067362,21.4281798 C55.895743,17.2972267 52.6253846,14.0267453 48.4948004,11.615998 C44.3636013,9.20512774 39.8535636,8 34.9614901,8 C30.0700314,8 25.5585181,9.20549662 21.4281798,11.615998 C17.2972267,14.0266224 14.0269912,17.2972267 11.615998,21.4281798 C9.20537366,25.5590099 8,30.0699084 8,34.9607523 C8,40.8357654 9.71405782,46.1187277 13.1430342,50.8109917 C16.5716416,55.5036246 21.0008949,58.7507436 26.4304251,60.5527176 C27.0624378,60.6700211 27.5302994,60.5875152 27.8345016,60.3072901 C28.1388268,60.0266961 28.290805,59.6752774 28.290805,59.2545094 C28.290805,59.1842994 28.2847799,58.5526556 28.2730988,57.3588401 C28.2610487,56.1650247 28.2553926,55.1235563 28.2553926,54.2349267 L27.4479164,54.3746089 C26.9330843,54.468919 26.2836113,54.5088809 25.4994975,54.4975686 C24.7157525,54.4866252 23.9021284,54.4044881 23.0597317,54.2517722 C22.2169661,54.1004088 21.4330982,53.749359 20.7075131,53.1993604 C19.982297,52.6493618 19.4674649,51.9294329 19.1631397,51.0406804 L18.8120898,50.2328353 C18.5780976,49.6950097 18.2097104,49.0975487 17.7064365,48.4426655 C17.2031625,47.7871675 16.6942324,47.3427912 16.1794003,47.108799 L15.9336039,46.9328437 C15.7698216,46.815909 15.6178435,46.6748743 15.4773006,46.511215 C15.3368806,46.3475556 15.2317501,46.1837734 15.1615401,46.0197452 C15.0912072,45.855594 15.1494901,45.7209532 15.3370036,45.6153308 C15.5245171,45.5097084 15.8633939,45.4584343 16.3551097,45.4584343 L17.0569635,45.5633189 C17.5250709,45.6571371 18.104088,45.9373622 18.7947525,46.4057156 C19.4850481,46.8737001 20.052507,47.4821045 20.4972521,48.230683 C21.0358155,49.1905062 21.6846737,49.9218703 22.4456711,50.4251443 C23.2060537,50.9284182 23.9727072,51.1796248 24.744894,51.1796248 C25.5170807,51.1796248 26.1840139,51.121096 26.7459396,51.0046532 C27.3072505,50.8875956 27.8338868,50.7116403 28.3256025,50.477771 C28.5362325,48.9090515 29.1097164,47.7039238 30.0455624,46.8615271 C28.7116959,46.721353 27.5124702,46.5102313 26.4472706,46.2295144 C25.3826858,45.9484285 24.2825656,45.4922482 23.1476478,44.8597436 C22.0121153,44.2280998 21.0701212,43.44374 20.3214198,42.5080169 C19.5725954,41.571802 18.9580429,40.3426971 18.4786232,38.821809 C17.9989575,37.300306 17.7590632,35.5451796 17.7590632,33.5559381 C17.7590632,30.7235621 18.6837199,28.3133066 20.5326645,26.3238191 C19.6665366,24.1944035 19.7483048,21.8072644 20.778215,19.1626478 C21.4569523,18.951772 22.4635002,19.1100211 23.7973667,19.6364115 C25.1314792,20.1630477 26.1082708,20.6141868 26.7287253,20.9882301 C27.3491798,21.3621504 27.8463057,21.6790175 28.2208409,21.9360032 C30.3978419,21.3277217 32.644438,21.0235195 34.9612442,21.0235195 C37.2780503,21.0235195 39.5251383,21.3277217 41.7022622,21.9360032 L43.0362517,21.0938524 C43.9484895,20.5319267 45.0257392,20.0169716 46.2654186,19.5488642 C47.5058357,19.0810026 48.4543466,18.9521409 49.1099676,19.1630167 C50.1627483,21.8077563 50.2565666,24.1947724 49.3901927,26.324188 C51.2390143,28.3136755 52.1640399,30.7245457 52.1640399,33.556307 C52.1640399,35.5455485 51.9232849,37.3062081 51.444357,38.8393922 C50.9648143,40.3728223 50.3449746,41.6006975 49.5845919,42.5256002 C48.8233486,43.4503799 47.8753296,44.2285916 46.7404118,44.8601125 C45.6052481,45.4921252 44.504759,45.9483056 43.4401742,46.2293914 C42.3750975,46.5104772 41.1758719,46.7217219 39.8420054,46.8621419 C41.0585683,47.9149226 41.6669728,49.5767225 41.6669728,51.846804 L41.6669728,59.2535257 C41.6669728,59.6742937 41.8132948,60.0255895 42.1061847,60.3063064 C42.3987058,60.5865315 42.8606653,60.6690374 43.492678,60.5516109 C48.922946,58.7498829 53.3521992,55.5026409 56.7806837,50.810008 C60.2087994,46.117744 61.923472,40.8347817 61.923472,34.9597686 C61.9222424,30.0695396 60.7162539,25.5590099 58.3067362,21.4281798 Z" id="Shape" fill="#FFFFFF">

</path>
        </g>
    </g>
</svg>)end";
    SkMemoryStream svgStream6(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream6);
    gAllSVGs.push_back(svgDom);

    svgXml = R"end(
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
	 width="800px" height="800px" viewBox="0 0 50.292 50.292"
	 xml:space="preserve">
<g>
	<g id="Layer_1_copy_46_">
		<path d="M41.258,32.354c0.227,0.231,0.34,0.605,0.34,1.121V36.1h-0.609v-2.619c0-0.32-0.067-0.562-0.204-0.722
			c-0.138-0.159-0.351-0.239-0.642-0.239c-0.377,0-0.658,0.107-0.84,0.325c-0.182,0.22-0.271,0.554-0.271,1.007v2.245h-0.608v-2.616
			c0-0.322-0.069-0.562-0.205-0.723c-0.137-0.161-0.353-0.24-0.643-0.24c-0.382,0-0.662,0.115-0.839,0.344
			c-0.178,0.229-0.268,0.604-0.268,1.125v2.11h-0.609v-4.022h0.496l0.101,0.551h0.028c0.115-0.195,0.275-0.348,0.486-0.458
			s0.443-0.166,0.703-0.166c0.629,0,1.041,0.228,1.232,0.683h0.029c0.121-0.211,0.293-0.377,0.521-0.498
			c0.229-0.123,0.486-0.185,0.777-0.185C40.691,32.001,41.031,32.119,41.258,32.354z M16.019,17.541l-0.005,0.023h0.005V17.541z
			 M19.43,32.547c0.29,0.365,0.435,0.876,0.435,1.534c0,0.66-0.147,1.174-0.442,1.54c-0.295,0.365-0.705,0.549-1.228,0.549
			c-0.262,0-0.501-0.048-0.718-0.146c-0.217-0.097-0.398-0.246-0.545-0.444h-0.044c0.03,0.233,0.044,0.458,0.044,0.668v1.653h-0.61
			v-5.828h0.496l0.084,0.552h0.03c0.156-0.22,0.339-0.379,0.546-0.478C17.686,32.048,17.925,32,18.194,32
			C18.729,32.001,19.14,32.184,19.43,32.547z M19.234,34.076c0-0.503-0.099-0.888-0.296-1.154s-0.474-0.401-0.832-0.401
			c-0.411,0-0.708,0.112-0.892,0.342c-0.184,0.228-0.278,0.588-0.282,1.086v0.136c0,0.565,0.094,0.97,0.282,1.213
			c0.188,0.244,0.49,0.365,0.907,0.365c0.348,0,0.62-0.142,0.816-0.423C19.136,34.958,19.234,34.569,19.234,34.076z M50.206,23.488
			c0.422,0.375-0.843,1.522-0.843,1.522c-1.356,1.568-1.764,1.969-1.764,1.969c-0.381,0.428-0.578,0.526-0.93,0.654
			c-0.354,0.127-1.055,0.21-1.055,0.21c-19.693,1.92-28.497-1.007-28.497-1.007c-2.169-0.725-4.424-1.842-5.022-2.146
			c-0.376,0.373-0.622,0.576-0.622,0.576c-2.951,2.458-6.135,2.623-6.135,2.623l-0.375-0.022c-0.139,0.002-0.274-0.003-0.405-0.011
			c0.15,0.011,0.241,0.011,0.241,0.011l0.351,0.022H4.94c-2.154,0-3.489-0.959-3.489-0.959C0,25.899,0,24.073,0,24.073
			c0.048-1.569,1.547-2.622,1.547-2.622c1.428-1.007,3.161-0.913,3.161-0.913c2.107,0.07,5.526,1.569,5.526,1.569
			c0.313,0.123,0.638,0.246,0.967,0.367c0.775-1.038,1.235-1.936,1.235-1.936c0.585-1.147,0.819-2.061,0.819-2.061H5.224v-0.913
			h3.793v-2.06H3.748V14.59h5.269v-1.662c0-0.281,0.632-0.422,0.632-0.422l0.609-0.046h1.428v2.13h5.457v0.914h-5.457v2.06h4.328
			l-0.135,0.702c-0.211,0.937-0.609,1.874-0.609,1.874c-0.503,1.202-1.206,2.258-1.87,3.096c1.886,0.622,3.462,1.072,3.462,1.072
			c0.745,0.214,1.595,0.39,2.506,0.537v-7.725c0,0-1.007,0.515-1.874,0.843L17.143,17.4c0,0,0.913-0.632,1.826-1.521
			c0,0,1.803-1.804,1.803-3.021c0,0,0-0.281,0.632-0.421l0.609-0.047h1.217l-0.046,0.445l-0.305,1.101c0,0-0.328,0.749-0.82,1.334
			v9.907c1.842,0.172,3.759,0.257,5.479,0.291v-9.027H22.48v-0.936h5.058v-2.646c0-0.281,0.633-0.421,0.633-0.421l0.608-0.047h1.451
			v3.115h1.404v0.936H30.23v9.049c1.865-0.009,3.113-0.058,3.113-0.058c1.664-0.067,3.23-0.166,4.684-0.281v-4.613h-3.629v-0.937
			h3.629v-2.341H32.76v-3.419c0-0.375,1.264-0.468,1.264-0.468h1.265v0.515l2.739-0.093V12.86c0-0.281,0.634-0.421,0.634-0.421
			l0.608-0.047h1.451v1.311l4.215-0.141c1.193,0,1.219,1.125,1.219,1.125l-0.211,1.545c-0.209,0.562-0.562,0.562-0.562,0.562h-0.116
			v0.468h-4.543v2.341h3.864v0.937h-3.864v4.367c5.534-0.571,8.875-1.323,8.875-1.323L50.206,23.488z M4.092,27.807
			c-1.159-0.182-1.913-0.689-1.913-0.689c-0.055-0.036-0.108-0.074-0.159-0.112c0.069,0.06,0.112,0.089,0.112,0.089
			C2.759,27.535,3.538,27.725,4.092,27.807z M10.161,23.705l-2.08-1.059c-0.573-0.224-0.439-0.172-1.616-0.632
			c-1.042-0.408-2.084-0.234-2.084-0.234c-0.053,0-0.105,0.003-0.157,0.005c-2.489,0.617-2.489,2.312-2.489,2.312
			c0,1.405,1.1,2.083,1.1,2.083c0.89,0.516,2.271,0.516,2.271,0.516c1.874,0,4.777-2.715,4.777-2.715
			C9.978,23.889,10.07,23.797,10.161,23.705z M43.65,16.346l0.187-1.428c-0.022-0.398-0.397-0.375-0.397-0.375l-2.715,0.094
			l-2.693,0.117v-0.023l-2.74,0.07v1.545H43.65z M22.982,32.329c0.23,0.213,0.347,0.554,0.347,1.023v2.746h-0.452l-0.12-0.574h-0.03
			c-0.201,0.252-0.401,0.422-0.6,0.513c-0.2,0.09-0.449,0.135-0.748,0.135c-0.399,0-0.71-0.104-0.938-0.31
			c-0.226-0.207-0.339-0.5-0.339-0.877c0-0.812,0.65-1.238,1.949-1.276l0.683-0.022v-0.248c0-0.316-0.068-0.55-0.205-0.699
			c-0.135-0.151-0.353-0.228-0.651-0.228c-0.335,0-0.714,0.104-1.138,0.31l-0.188-0.467c0.199-0.107,0.416-0.191,0.651-0.252
			c0.236-0.062,0.473-0.094,0.711-0.094C22.395,32.008,22.751,32.114,22.982,32.329z M22.719,34.12l-0.608,0.025
			c-0.484,0.018-0.834,0.092-1.048,0.227c-0.214,0.134-0.321,0.34-0.321,0.621c0,0.221,0.067,0.39,0.2,0.504
			c0.133,0.113,0.32,0.172,0.56,0.172c0.379,0,0.677-0.105,0.894-0.312s0.325-0.5,0.325-0.873v-0.361h-0.002V34.12z M34.822,32.565
			c0.33,0.375,0.496,0.881,0.496,1.519c0,0.655-0.166,1.168-0.496,1.537c-0.329,0.368-0.786,0.553-1.368,0.553
			c-0.358,0-0.679-0.085-0.957-0.254c-0.279-0.169-0.494-0.411-0.646-0.728c-0.15-0.314-0.228-0.687-0.228-1.108
			c0-0.656,0.164-1.166,0.491-1.532c0.326-0.365,0.783-0.549,1.365-0.549C34.043,32.001,34.49,32.19,34.822,32.565z M34.688,34.083
			c0-0.512-0.104-0.898-0.311-1.165s-0.514-0.397-0.916-0.397c-0.398,0-0.701,0.131-0.902,0.394
			c-0.203,0.262-0.305,0.651-0.305,1.17c0,0.515,0.104,0.905,0.309,1.175c0.207,0.27,0.508,0.402,0.906,0.402s0.701-0.133,0.908-0.4
			C34.585,34.989,34.688,34.6,34.688,34.083z M27.667,35.209c-0.142,0-0.248,0.042-0.321,0.126
			c-0.074,0.084-0.113,0.208-0.113,0.373c0,0.176,0.041,0.303,0.123,0.38c0.084,0.077,0.188,0.116,0.312,0.116
			c0.141,0,0.25-0.042,0.33-0.129s0.123-0.207,0.123-0.367c0-0.164-0.041-0.288-0.121-0.373
			C27.918,35.252,27.807,35.209,27.667,35.209z M30.428,32.542c0.123,0,0.264,0.018,0.422,0.053s0.307,0.08,0.439,0.135l0.188-0.519
			c-0.108-0.058-0.262-0.104-0.455-0.146c-0.192-0.043-0.387-0.063-0.58-0.063c-0.6,0-1.062,0.185-1.387,0.55
			c-0.324,0.368-0.486,0.889-0.486,1.561c0,0.656,0.16,1.164,0.479,1.522c0.32,0.356,0.771,0.538,1.354,0.538
			c0.408,0,0.748-0.07,1.016-0.209v-0.54c-0.354,0.146-0.695,0.218-1.031,0.218c-0.391,0-0.687-0.133-0.885-0.396
			c-0.201-0.265-0.299-0.646-0.299-1.14C29.202,33.063,29.611,32.542,30.428,32.542z M24.776,21.498c0,0,0.282,0.282,0.562,0
			l0.984-0.89l0.865-1.007c0,0,0.306-0.257,0-0.585l-0.865-0.983l-0.984-0.866c0,0-0.28-0.281-0.562,0l-0.983,0.866l-0.89,0.983
			c0,0-0.257,0.328,0,0.585l0.866,1.007L24.776,21.498z M44.704,21.498l-0.75-0.655c0,0-0.209-0.211-0.443,0l-0.75,0.655
			l-0.655,0.75c0,0-0.188,0.234,0,0.444l0.655,0.75l0.75,0.656c0,0,0.234,0.234,0.443,0l0.75-0.656l0.68-0.75
			c0,0,0.164-0.21,0-0.444L44.704,21.498z M11.342,30.709l2.111,5.388h-0.646l-0.668-1.706H9.987l-0.66,1.706H8.696l2.122-5.388
			H11.342z M11.944,33.83l-0.623-1.663c-0.082-0.211-0.164-0.469-0.25-0.773c-0.053,0.233-0.13,0.492-0.231,0.773l-0.631,1.663
			H11.944z M14.948,36.097h0.61v-4.022h-0.61V36.097z M25.543,34.862c-0.101,0.303-0.168,0.517-0.2,0.641h-0.029
			c-0.046-0.23-0.167-0.609-0.36-1.134l-0.88-2.296h-0.655l1.623,4.047l-0.224,0.57c-0.179,0.472-0.478,0.705-0.896,0.705
			c-0.167,0-0.317-0.014-0.451-0.043v0.487c0.18,0.042,0.364,0.063,0.55,0.063c0.333,0,0.613-0.094,0.842-0.285
			c0.229-0.189,0.429-0.51,0.6-0.963l1.729-4.582H26.54C25.976,33.63,25.644,34.561,25.543,34.862z M47.374,13.607h0.142v-1.054
			h0.397v-0.164h-0.938v0.164h0.398L47.374,13.607L47.374,13.607z M13.573,36.097h0.608v-5.711h-0.608V36.097z M48.238,12.601
			l0.353,1.007h0.142l0.328-0.984v0.984h0.164v-1.218h-0.209l-0.353,1.031l-0.353-1.031h-0.233v1.218h0.164v-1.007H48.238z
			 M15.255,30.581c-0.102,0-0.188,0.031-0.257,0.097c-0.068,0.064-0.103,0.167-0.103,0.308c0,0.138,0.035,0.24,0.103,0.307
			c0.069,0.066,0.155,0.102,0.257,0.102c0.099,0,0.183-0.035,0.254-0.102c0.07-0.066,0.106-0.169,0.106-0.307
			s-0.036-0.238-0.106-0.306C15.438,30.612,15.354,30.581,15.255,30.581z"/>
	</g>
</g>
</svg>)end";
    SkMemoryStream svgStream7(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream7);
    gAllSVGs.push_back(svgDom);

    svgXml = R"end(<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="14.2798" y="17.01" width="8" height="1.6" rx="0.8" fill="black"/>
<rect x="19.0796" y="13.8101" width="8" height="1.6" rx="0.8" transform="rotate(90 19.0796 13.8101)" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0002 3.29995C9.95674 3.29995 8.3002 4.9565 8.3002 6.99995V8.83091C8.3002 10.0592 8.70904 11.2525 9.46224 12.2227L10.3792 13.4038C11.2327 14.5032 10.789 16.1142 9.49299 16.6215L3.44218 18.9903C3.35654 19.0238 3.3002 19.1064 3.3002 19.1984V20C3.3002 20.1104 3.38974 20.2 3.5002 20.2H12.0002C12.442 20.2 12.8002 20.5581 12.8002 21C12.8002 21.4418 12.442 21.8 12.0002 21.8H3.5002C2.50608 21.8 1.7002 20.9941 1.7002 20V19.1984C1.7002 18.4478 2.16004 17.774 2.85891 17.5004L8.90972 15.1316C9.21044 15.0139 9.31339 14.6401 9.11536 14.385L8.1984 13.2039C7.2273 11.953 6.7002 10.4145 6.7002 8.83091V6.99995C6.7002 4.07284 9.07309 1.69995 12.0002 1.69995C14.9273 1.69995 17.3002 4.07284 17.3002 6.99995V8.84974C17.3002 9.92871 17.056 10.9937 16.5859 11.9649L16.5762 11.9848C16.3837 12.3825 15.9053 12.5489 15.5076 12.3564C15.1099 12.1639 14.9436 11.6854 15.1361 11.2877L15.1457 11.2678C15.5106 10.5139 15.7002 9.68726 15.7002 8.84974V6.99995C15.7002 4.9565 14.0436 3.29995 12.0002 3.29995Z" fill="black"/>
</svg>
)end";
    SkMemoryStream svgStream8(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream8);
    gAllSVGs.push_back(svgDom);

    // 由于OH_Drawing_TextBlobBuilderAllocRunPos接口限制，目前仅支持不带旋转缩放的text svg渲染
    svgXml = R"(
    <svg width="300" height="120">
        <rect x="0" y="0" width="300" height="120" fill="#EEE"/>
        <text x="30" y="70" font-size="48" font-family="sans-serif" fill="red">SVG Text</text>
    </svg>
    )";
    
    SkMemoryStream svgStream9(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream9);
    
    gAllSVGs.push_back(svgDom);

    svgXml = R"SVG(<svg width="400" height="120">
        <defs>
            <linearGradient id="g" gradientUnits="objectBoundingBox" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0%" stop-color="red"/>
              <stop offset="100%" stop-color="blue"/>
            </linearGradient>
        </defs>
    <text x="40" y="80" font-size="48" fill="url(#g)">Hello</text></svg>)SVG";

    SkMemoryStream svgStream10(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream10);
    
    gAllSVGs.push_back(svgDom);

    svgXml = R"SVG(<svg width="400" height="120">
      <clipPath id="clip">
        <text x="40" y="80" font-size="48">
          <tspan rotate="-10">H</tspan>
          <tspan rotate="0">e</tspan>
          <tspan rotate="10">l</tspan>
          <tspan rotate="20">l</tspan>
          <tspan rotate="30">o</tspan>
        </text>
      </clipPath>
      <rect width="400" height="120" fill="orange" clip-path="url(#clip)" />
    </svg>)SVG";

    SkMemoryStream svgStream11(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream11);
    
    gAllSVGs.push_back(svgDom);

    svgXml = R"SVG(<svg width="400" height="120">
      <g transform="rotate(-15 200 70) scale(1.3 1.1)">
        <text x="30" y="70" font-size="48" font-family="sans-serif" fill="red">
          <tspan rotate="-10" font-size="50">S</tspan>
          <tspan rotate="10" font-size="42">V</tspan>
          <tspan rotate="25" font-size="48">G</tspan>
          <tspan rotate="-20" dx="50" dy="50" font-size="60">T</tspan>
          <tspan rotate="7" font-size="48">e</tspan>
          <tspan rotate="-5" font-size="48">x</tspan>
          <tspan rotate="12" font-size="45">t</tspan>
        </text>
      </g>
    </svg>)SVG";

    SkMemoryStream svgStream12(svgXml, strlen(svgXml), true);
    svgDom = SkSVGDOM::MakeFromStream(svgStream12);
    
    gAllSVGs.push_back(svgDom);

}

DEF_TEST_CANVAS_WITH_HEIGHT(drawSVG, TEST_LEVEL::NORMAL, 500) {
    if (gAllSVGs.size() == 0) {
        PrepareSVGs();
    }

    auto svgDom = gAllSVGs[0];
    svgDom->render(&test_canvas);
    test_canvas.translate(500, 0);

    svgDom = gAllSVGs[1];
    svgDom->render(&test_canvas);

    svgDom = gAllSVGs[2];
    test_canvas.translate(0, 100);
    svgDom->render(&test_canvas);

    svgDom = gAllSVGs[3];
    test_canvas.translate(0, 100);
    test_canvas.scale(0.1, 0.1);
    svgDom->render(&test_canvas);
    test_canvas.scale(10, 10);


    svgDom = gAllSVGs[4];
    test_canvas.translate(0, 100);
    test_canvas.scale(0.1, 0.1);
    svgDom->render(&test_canvas);
    test_canvas.scale(10, 10);

    svgDom = gAllSVGs[5];
    test_canvas.translate(100, -300);
    test_canvas.scale(0.1, 0.1);
    svgDom->render(&test_canvas);
    test_canvas.scale(10, 10);

    svgDom = gAllSVGs[6];
    test_canvas.translate(100, 0);
    test_canvas.scale(0.1, 0.1);
    svgDom->render(&test_canvas);
    test_canvas.scale(10, 10);

    svgDom = gAllSVGs[7];
    test_canvas.translate(100, 0);
    test_canvas.scale(10, 10);
    svgDom->render(&test_canvas);
    test_canvas.scale(0.1, 0.1);

    SkBitmap bitmap;
//    bitmap.tryAllocN32Pixels(250, 250, true);
    SkImageInfo info = SkImageInfo::Make(250, 250, kAlpha_8_SkColorType, kPremul_SkAlphaType);
    bitmap.setInfo(info);
    bitmap.allocPixels();
    bitmap.setImmutable();
    auto image = bitmap.asImage();
    SkCanvas bitmap_canvas(bitmap);
    bitmap_canvas.scale(10, 10);
    svgDom->render(&bitmap_canvas);
    bitmap_canvas.scale(0.1, 0.1);

    test_canvas.translate(250, 0);
    SkSamplingOptions option(SkFilterMode::kLinear, SkMipmapMode::kLinear);
    
    SkRect src = SkRect::MakeXYWH(0, 0, 250, 250);
    SkRect dst = SkRect::MakeXYWH(0, 0, 250, 250);

    test_canvas.drawImageRect(bitmap.asImage(), src, dst, option, nullptr, SkCanvas::kStrict_SrcRectConstraint);
    test_canvas.drawImage(image, 250, 0);

    svgDom = gAllSVGs[8];
    test_canvas.translate(-200, 300);
    svgDom->render(&test_canvas);

    svgDom = gAllSVGs[9];
    test_canvas.translate(300, 0);
    svgDom->render(&test_canvas);

    svgDom = gAllSVGs[10];
    test_canvas.translate(0, 80);
    svgDom->render(&test_canvas);

    svgDom = gAllSVGs[11];
    test_canvas.translate(150, 0);
    svgDom->render(&test_canvas);
}

DEF_TEST_CANVAS(drawVertices1, TEST_LEVEL::NORMAL) {
    // 定义顶点模式 (Triangles)
    SkVertices::VertexMode mode = SkVertices::kTriangles_VertexMode;

    // 定义顶点坐标
    SkPoint positions1[] = {
        {50, 50},  // 顶点1
        {150, 50}, // 顶点2
        {100, 150} // 顶点3
    };

    // 定义顶点颜色 (红、绿、蓝)
    SkColor colors1[] = {
        SK_ColorRED,    // 顶点1的颜色
        SK_ColorGREEN,  // 顶点2的颜色
        SK_ColorBLUE    // 顶点3的颜色
    };

    // 创建顶点对象
    auto vertices1 = SkVertices::MakeCopy(mode, 3, positions1, nullptr, colors1);

    // 绘制第一个三角形
    SkPaint paint1;
    paint1.setAntiAlias(true);
    test_canvas.drawVertices(vertices1, SkBlendMode::kSrcOver, paint1);

    // 定义另一个三角形 (使用 TriangleFan 模式)
    SkVertices::VertexMode mode2 = SkVertices::kTriangleFan_VertexMode;
    SkPoint positions2[] = {
        {200, 100}, // 顶点中心
        {250, 50},  // 顶点2
        {300, 100}, // 顶点3
        {250, 150}  // 顶点4
    };

    // 顶点颜色 (黄色、青色、洋红、白色)
    SkColor colors2[] = {
        SK_ColorYELLOW, // 顶点1
        SK_ColorCYAN,   // 顶点2
        SK_ColorMAGENTA,// 顶点3
        SK_ColorWHITE   // 顶点4
    };

    // 创建顶点对象
    auto vertices2 = SkVertices::MakeCopy(mode2, 4, positions2, nullptr, colors2);

    // 绘制第二个三角形
    SkPaint paint2;
    paint2.setAntiAlias(true);
    paint2.setStrokeWidth(5);
    paint2.setStyle(SkPaint::kFill_Style);
    test_canvas.drawVertices(vertices2, SkBlendMode::kModulate, paint2);
}

DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicPoint, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStrokeWidth(714);
    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    switch (drawCounter) {
        case 0: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 255));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 1: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 255));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 2: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 0));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 3: {
            paint.setColor(SkColorSetARGB(128, 128, 128, 255));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 4: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 0));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 5: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 128));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 6: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 255));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 7: {
            paint.setColor(SkColorSetARGB(128, 255, 255, 255));
            test_canvas.drawPoint(400, 400, paint);
        }
        case 8: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 128));
            test_canvas.drawPoint(400, 400, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasic, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    sk_sp<SkMaskFilter> blurFilter1 = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 10.0f);
    sk_sp<SkMaskFilter> blurFilter2 = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 100.0f);
    paint.setMaskFilter(blurFilter1);
    switch (drawCounter) {
        case 0: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 1: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 2: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 0));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 3: {
            paint.setColor(SkColorSetARGB(128, 128, 128, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 4: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 0));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 5: {
            paint.setMaskFilter(blurFilter2);
            paint.setColor(SkColorSetARGB(128, 0, 128, 128));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 6: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 7: {
            paint.setColor(SkColorSetARGB(128, 255, 255, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 8: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 128));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasic3, TEST_LEVEL::NORMAL, 1000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(300);
    switch (drawCounter) {
        case 0: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 255));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({100, 0, 500, 1000}, paint);
        }
        case 1: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 255));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({200, 0, 600, 1000}, paint);
        }
        case 2: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 0));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({300, 0, 700, 1000}, paint);
        }
        case 3: {
            paint.setColor(SkColorSetARGB(128, 128, 128, 255));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({400, 0, 800, 1000}, paint);
        }
        case 4: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 0));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({500, 0, 900, 1000}, paint);
        }
        case 5: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 128));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({600, 0, 1000, 1000}, paint);
        }
        case 6: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 255));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({700, 0, 1100, 1000}, paint);
        }
        case 7: {
            paint.setColor(SkColorSetARGB(128, 255, 255, 255));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({800, 0, 1200, 1000}, paint);
        }
        case 8: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 128));
            test_canvas.drawRect({100, 50, 1100, 1050}, paint);
//            test_canvas.drawRect({900, 0, 1300, 1000}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicOval, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(100);
    switch (drawCounter) {
        case 0: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 255));
            test_canvas.drawOval({50, 50, 100, 400}, paint);
        }
        case 1: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 255));
            test_canvas.drawOval({50, 50, 150, 400}, paint);
        }
        case 2: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 0));
            test_canvas.drawOval({50, 50, 200, 400}, paint);
        }
        case 3: {
            paint.setColor(SkColorSetARGB(128, 128, 128, 255));
            test_canvas.drawOval({50, 50, 300, 400}, paint);
        }
        case 4: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 0));
            test_canvas.drawOval({50, 50, 400, 400}, paint);
        }
        case 5: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 128));
            test_canvas.drawOval({50, 50, 400, 300}, paint);
        }
        case 6: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 255));
            test_canvas.drawOval({50, 50, 400, 200}, paint);
        }
        case 7: {
            paint.setColor(SkColorSetARGB(128, 255, 255, 255));
            test_canvas.drawOval({50, 50, 400, 150}, paint);
        }
        case 8: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 128));
            test_canvas.drawOval({50, 50, 400, 100}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicRRect, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(100);
    paint.setColor(SkColorSetARGB(128, 0, 128, 200));
    SkRRect rrect;
    rrect.setRectXY({50, 50, 600, 350}, 100, 100);
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 1: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 2: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 3: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 4: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 5: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 6: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 7: {
            test_canvas.drawRRect(rrect, paint);
        }
        case 8: {
            test_canvas.drawRRect(rrect, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicDRRect, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(100);
    paint.setColor(SkColorSetARGB(128, 0, 128, 200));
    SkRRect rrect;
    rrect.setRectXY({50, 50, 600, 350}, 100, 100);
    
    SkRRect rrect2;
    rrect2.setRectXY({250, 150, 400, 250}, 30, 30);
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 1: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 2: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 3: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 4: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 5: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 6: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 7: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        case 8: {
            test_canvas.drawDRRect(rrect, rrect2, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicArc, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(100);
    paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
    paint.setColor(SkColorSetARGB(128, 0, 128, 200));
    
    SkRect rect = {50, 50, 600, 350};
    test_canvas.translate(100, 0);
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawArc(rect, 90, 270, false, paint);
        }
        case 1: {
            test_canvas.drawArc(rect, 50, 200, false, paint);
        }
        case 2: {
            test_canvas.drawArc(rect, 100, 270, false, paint);
        }
        case 3: {
            test_canvas.drawArc(rect, 200, 270, false, paint);
        }
        case 4: {
            test_canvas.drawArc(rect, 100, 100, false, paint);
        }
        case 5: {
            test_canvas.drawArc(rect, 200, 70, false, paint);
        }
        case 6: {
            test_canvas.drawArc(rect, 30, 200, false, paint);
        }
        case 7: {
            test_canvas.drawArc(rect, 60, 220, false, paint);
        }
        case 8: {
            test_canvas.drawArc(rect, 30, 7070, false, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicPicture, TEST_LEVEL::NORMAL, 400) {
    static int drawCounter = 0;
    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(100);
    paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
    paint.setColor(SkColorSetARGB(128, 0, 128, 200));
    
    
    static SkPictureRecorder recorder1;
    static SkPictureRecorder recorder2;
    static sk_sp<SkPicture> picture1 = nullptr;
    static sk_sp<SkPicture> picture2 = nullptr;
    
    if (!picture1) {
        SkCanvas *recordCanvas = recorder1.beginRecording(1000, 1000);
        TestCanvas_markGroupTestBasicArc(*recordCanvas);
        picture1 = recorder1.finishRecordingAsPicture();
        
        recordCanvas = recorder1.beginRecording(1000, 1000);
        TestCanvas_markGroupTestBasicDRRect(*recordCanvas);
        picture2 = recorder1.finishRecordingAsPicture();
    }
    
    test_canvas.translate(drawCounter, 0);

    test_canvas.drawPicture(picture1);
    test_canvas.translate(300 + drawCounter, 50);
    
    test_canvas.drawPicture(picture1);
    
    drawCounter = (drawCounter + 1) % 10;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasic2, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(100, 100, 1000, 1000);
    switch (drawCounter) {
        case 0: {
            test_canvas.clear(SkColorSetARGB(128, 255, 0, 0));
            break;
        }
        case 1: {
            test_canvas.clipRect(normalRect);
            test_canvas.clear(SkColorSetARGB(255, 0, 128, 255));
            break;
        }
        case 2: {
            paint.setColor(SK_ColorRED);
            paint.setStrokeWidth(100);
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawRect(normalRect, paint);
            break;
        }
        case 3: {
            paint.setStrokeWidth(100);
            paint.setStrokeCap(SkPaint::Cap::kSquare_Cap);
            paint.setStroke(true);
            paint.setAntiAlias(false);
            paint.setColor(SK_ColorRED);
            test_canvas.drawLine(100, 100, 1100, 1100, paint);
            break;
        }
        case 4: {
            paint.setStrokeWidth(100);
            paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
            paint.setStroke(true);
            paint.setAntiAlias(false);
            paint.setColor(SK_ColorRED);
            test_canvas.drawLine(100, 100, 1100, 1100, paint);
            break;
        }
        case 5: {
            paint.setStrokeWidth(100);
            paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
            paint.setStroke(true);
            paint.setAntiAlias(true);
            paint.setColor(SK_ColorRED);
            test_canvas.drawLine(100, 100, 1100, 1100, paint);
            break;
        }
        case 6: {
            paint.setColor(SK_ColorBLUE);
            test_canvas.drawArc(normalRect, 0, 200, false, paint);
            break;
        }
        case 7: {
            paint.setColor(SK_ColorBLUE);
            test_canvas.drawOval(normalRect, paint);
            break;
        }
        case 8: {
            SkRRect rrect;
            rrect.setRectXY(normalRect, 100, 100);
            test_canvas.drawRRect(rrect, paint);
            break;
        }
        case 9: {
            SkRRect rrect_outer;
            SkRRect rrect_inner;
            paint.setStroke(false);
            rrect_outer.setRectXY(normalRect, 100, 100);
            rrect_inner.setRectXY({200, 200, 800, 800}, 100, 100);
            test_canvas.drawDRRect(rrect_outer, rrect_inner, paint);
            break;
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}

DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasic4, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(100, 100, 1000, 1000);
    switch (drawCounter) {
        
        case 0: {
            paint.setColor(SK_ColorBLUE);
            test_canvas.drawOval(normalRect, paint);
            break;
        }
        case 1: {
            SkRRect rrect;
            rrect.setRectXY(normalRect, 100, 100);
            test_canvas.drawRRect(rrect, paint);
            break;
        }
        default:
        case 2: {
            SkRRect rrect_outer;
            SkRRect rrect_inner;
            paint.setStroke(false);
            rrect_outer.setRectXY(normalRect, 100, 100);
            rrect_inner.setRectXY({200, 200, 800, 800}, 100, 100);
            test_canvas.drawDRRect(rrect_outer, rrect_inner, paint);
            break;
        }
        break;
    }
    drawCounter = (drawCounter + 1) % 8;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicColorFilter, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    sk_sp<SkColorFilter> color_filter = SkColorFilters::Blend(SkColorSetARGB(100, 0, 255, 0), SkBlendMode::kSrcOver);
    
    SkColorMatrix matrix;
    // enhance red
    matrix.setScale(10.0f, 1.0f, 1.0f, 1.0f);
    sk_sp<SkColorFilter> color_filter2 = SkColorFilters::Matrix(matrix);
    
    SkColorMatrix matrix1;
    matrix1.setScale(-1.0f, -1.0f, -1.0f, 1.0f);
    matrix1.postTranslate(1.0f, 1.0f, 1.0f, 0);
    paint.setColor(SkColorSetARGB(255, 128, 255, 0));
    sk_sp<SkColorFilter> color_filter5 = SkColorFilters::Matrix(matrix1);
    
    sk_sp<SkColorFilter> color_filter6 = SkColorFilters::Compose(color_filter5, color_filter2);
    
    sk_sp<SkColorFilter> color_filter7 = SkColorFilters::Compose(color_filter2, color_filter5);
    
    sk_sp<SkColorFilter> color_filter8 =
        SkColorMatrixFilter::MakeLightingFilter(SkColorSetRGB(128, 128, 128), SkColorSetRGB(64, 64, 64));

    
    switch (drawCounter) {
        case 0: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 255));
            paint.setColorFilter(color_filter);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 1: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 255));
            paint.setColorFilter(color_filter2);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 2: {
            paint.setColor(SkColorSetARGB(128, 0, 0, 0));
            paint.setColorFilter(color_filter5);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 3: {
            paint.setColor(SkColorSetARGB(128, 128, 128, 255));
            paint.setColorFilter(color_filter6);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 4: {
            paint.setColor(SkColorSetARGB(128, 0, 128, 0));
            paint.setColorFilter(color_filter7);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 5: {
            paint.setColorFilter(color_filter8);
            paint.setColor(SkColorSetARGB(128, 0, 128, 128));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 6: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 7: {
            paint.setColorFilter(nullptr);
            paint.setColor(SkColorSetARGB(128, 255, 255, 255));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 8: {
            paint.setColor(SkColorSetARGB(128, 255, 128, 128));
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}




DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicColorShader, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SK_ColorBLUE);
    paint.setBlendMode(SkBlendMode::kSrcOver);
    // 定义渐变的起点和终点
    SkPoint points[2] = {{0, 50}, {800, 800}};

    // 渐变颜色数组（从红色到蓝色）
    SkColor colors[2] = {SkColorSetARGB(128, 255, 0, 0), SK_ColorBLUE};
    // 生成线性渐变 Shader
    sk_sp<SkShader> shader1 = SkGradientShader::MakeLinear(points, colors, nullptr, 2, SkTileMode::kClamp);
    paint.setShader(shader1);
    
    SkPoint center = SkPoint::Make(800, 1000);
    sk_sp<SkShader> shader2 = SkGradientShader::MakeRadial(center, 80, colors, nullptr, 2, SkTileMode::kClamp);
    paint.setShader(shader2);
    
    
    SkScalar positions2[] = {0.0f, 0.5f, 1.0f};
    SkColor colors4[] = {SkColorSetARGB(128, 255, 0, 0), SkColorSetARGB(200, 0, 0, 255), SK_ColorGREEN};

    // 圆锥渐变的两个焦点（小圆中心和大圆中心）
    SkPoint start = SkPoint::Make(1800, 1000);       // 小圆中心
    SkScalar startRadius = 200;                              // 小圆半径
    SkPoint end = SkPoint::Make(2000, 1000); // 大圆中心
    SkScalar endRadius = 500;                               // 大圆半径

    // 创建渐变着色器
    sk_sp<SkShader> shader5 =
        SkGradientShader::MakeTwoPointConical(start, startRadius,     // 小圆
                                              end, endRadius,         // 大圆
                                              colors4, positions2, 3, // 颜色 & 位置
                                              SkTileMode::kClamp // Tile 模式（kClamp: 超出范围的部分保持边缘颜色）
        );

    paint.setShader(shader5);
    
    SkScalar positions1[] = {0.0f, 0.5f, 1.0f}; // 颜色在渐变中的位置
                                                // 额外参数：startAngle 和 endAngle
    SkScalar startAngle = 0.0f;                         // 从 90° 开始渐变
    SkScalar endAngle = 360.0f;                          // 结束在 270°

    sk_sp<SkShader> shader4 = SkGradientShader::MakeSweep(center.fX, center.fY, // 渐变中心点
                                                          colors4, positions1, 3, // 颜色数组、颜色位置、颜色数量
                                                          SkTileMode::kClamp,   // 颜色填充模式
                                                          startAngle, endAngle, // 起始角度、终止角度
                                                          0, nullptr);
    paint.setShader(shader4);
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 1: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 2: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 3: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 4: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 5: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 6: {
            
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 7: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 8: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}




DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestPathEffect, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    
    SkPaint paintEffect;
    paintEffect.setStyle(SkPaint::kStroke_Style);
    paintEffect.setStrokeWidth(20);
    paintEffect.setColor(SkColorSetARGB(128, 0, 128, 0));
    
    auto cornerEffect = SkCornerPathEffect::Make(30); // 圆角半径为30
    paintEffect.setPathEffect(cornerEffect);
    
    // 虚线效果
    SkScalar intervals[] = {15, 10}; // 线段长度 + 间隔
    auto dash = SkDashPathEffect::Make(intervals, 2, 0);
    
    // 组合：先圆角，再虚线
    auto composed1 = SkPathEffect::MakeCompose(dash, cornerEffect);
    paintEffect.setPathEffect(composed1);
    
    auto composed2 = SkPathEffect::MakeCompose(cornerEffect, dash);
    paintEffect.setPathEffect(composed2);
    
    SkPath path;
    path.moveTo(50, 50);
    path.lineTo(500, 50);
    path.lineTo(500, 550);
    path.lineTo(50, 1000);
    path.close();
    
        // 构造重复的图案：一个小三角形
    SkPath stamp;
    stamp.moveTo(0, 0);
    stamp.lineTo(20, 10);
    stamp.lineTo(0, 20);
    stamp.close();
    
    auto effect = SkPath1DPathEffect::Make(stamp, 20, 0, SkPath1DPathEffect::kRotate_Style);

    paintEffect.setPathEffect(effect);
    
    
    switch (drawCounter) {
        case 0: {
            test_canvas.drawPath(path, paintEffect);
        }
        case 1: {
            test_canvas.drawPath(path, paintEffect);
        }
        case 2: {
            paintEffect.setPathEffect(composed2);
            test_canvas.drawPath(path, paintEffect);
        }
        case 3: {
            test_canvas.drawPath(path, paintEffect);
        }
        case 4: {
            paintEffect.setPathEffect(composed1);
            test_canvas.drawPath(path, paintEffect);
        }
        case 5: {
            test_canvas.drawPath(path, paintEffect);
        }
        case 6: {
            paintEffect.setPathEffect(cornerEffect);
            test_canvas.drawPath(path, paintEffect);
        }
        case 7: {
            test_canvas.drawPath(path, paintEffect);
        }
        case 8: {
            paintEffect.setPathEffect(nullptr);
            test_canvas.drawPath(path, paintEffect);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}




DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicClipTest, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPath starPath;
    SkPath rectPath;
    float cx = 200, cy = 200, r_outer = 100, r_inner = 40;
    int num_points = 5;
    // 外层五角星（顺时针）
    for (int i = 0; i < num_points * 2; ++i) {
        float angle = i * SK_ScalarPI / num_points;
        float r = (i % 2 == 0) ? r_outer : r_inner;
        float x = cx + r * cosf(angle);
        float y = cy + r * sinf(angle);
        if (i == 0) starPath.moveTo(x, y);
        else        starPath.lineTo(x, y);
    }
    starPath.close();
    
    // 内层小五角星（逆时针，做洞）
    float r_outer2 = 55, r_inner2 = 23; // 控制小星的大小
    SkPath smallStar;
    for (int i = 0; i < num_points * 2; ++i) {
        float angle = -i * SK_ScalarPI / num_points; // 逆时针
        float r = (i % 2 == 0) ? r_outer2 : r_inner2;
        float x = cx + r * cosf(angle);
        float y = cy + r * sinf(angle);
        if (i == 0) smallStar.moveTo(x, y);
        else        smallStar.lineTo(x, y);
    }
    smallStar.close();

    // 把小星洞加进大星路径（作为逆向子路径）
    starPath.addPath(smallStar);

//    SkPath reversePath;
//    reversePath.reverseAddPath(starPath);
    
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(0, 0, 3000, 2500);
    paint.setColor(SkColorSetARGB(128, 0, 128, 0));
    paint.setBlendMode(SkBlendMode::kSrcOver);
    
    
    SkRect rect = SkRect::MakeLTRB(100, 100, 300, 300);
    SkVector radii[4] = {{40, 40}, {40, 40}, {40, 40}, {40, 40}};
    SkRRect rrect;
    rrect.setRectRadii(rect, radii);
    
    rectPath.addRect({200, 200, 1400, 1600});
    
    switch (drawCounter) {
        case 0: {
            test_canvas.save();
            test_canvas.clipRRect(rrect);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
            test_canvas.restore();
        }
        case 1: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 2: {
            test_canvas.save();
            test_canvas.clipRect({200, 200, 1500, 1500});
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
            test_canvas.restore();
        }
        case 3: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 4: {
            test_canvas.save();
            test_canvas.clipPath(starPath, SkClipOp::kDifference);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
            test_canvas.restore();
        }
        case 5: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 6: {
            test_canvas.save();
            test_canvas.clipPath(rectPath);
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
            test_canvas.restore();
        }
        case 7: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        case 8: {
            test_canvas.drawRect({0, 0, 3000, 2500}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 10;
}



DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicCircle, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(100, 100, 1000, 1000);
    
    paint.setColor(SkColorSetARGB(128, 0, 128, 0));
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStrokeWidth(714);
    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    paint.setStyle(SkPaint::kFill_Style);

    switch (drawCounter) {
        case 0: {
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawPoint(400, 400, paint);
        }
        case 1: {
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawPoint(400, 400, paint);
        }
        case 2: {
            paint.setStyle(SkPaint::kFill_Style);
            test_canvas.drawCircle(400, 400, 357, paint);
        }
        case 3: {
            test_canvas.drawCircle(400, 400, 357, paint);
        }
        case 4: {
            test_canvas.drawOval({400 - 357, 400 - 357, 400 + 357, 400 + 357}, paint);
        }
        case 5: {
            test_canvas.drawOval({400 - 357, 400 - 357, 400 + 357, 400 + 357}, paint);
        }
        case 6: {
            test_canvas.drawOval({400 - 357, 400 - 357, 400 + 357 - 100, 400 + 357 + 100}, paint);
        }
        case 7: {
            test_canvas.drawOval({400 - 357, 400 - 357, 400 + 357 + 100, 400 + 357 - 100}, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 9;
}


DEF_TEST_CANVAS_WITH_HEIGHT(markGroupTestBasicCircleStroke, TEST_LEVEL::NONE, 2000) {
    static int drawCounter = 0;
    SkPaint paint;
    SkRect normalRect = SkRect::MakeXYWH(100, 100, 1000, 1000);
    
    paint.setColor(SkColorSetARGB(128, 0, 128, 0));
    paint.setBlendMode(SkBlendMode::kSrcOver);
    paint.setStrokeWidth(150);
    paint.setStrokeCap(SkPaint::Cap::kRound_Cap);
    paint.setStyle(SkPaint::kFill_Style);

    switch (drawCounter) {
        case 0: {
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawCircle(700, 700, 500 - 75, paint);
        }
        case 1: {
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawCircle(700, 700, 500 - 75, paint);
        }
        case 2: {
            paint.setStyle(SkPaint::kStroke_Style);
            test_canvas.drawCircle(700, 700, 500 - 75, paint);
        }
        default:
        break;
    }
    drawCounter = (drawCounter + 1) % 3;
}






// @todo: canvas concat translate scale rotate skew test

// @todo: canvas setMatrix resetMatrix getLocalToDevice test


// @todo: new canvas with bitmap and readPixel, writePixel
                                                                      
// @todo OH_Drawing_FontGetPathForGlyph test